Skip to content

Commit cbe7d93

Browse files
authored
feat: preserve metadata types when adding images in cells (#216)
1 parent 6b235a4 commit cbe7d93

3 files changed

Lines changed: 129 additions & 7 deletions

File tree

src/index.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,7 +1453,8 @@ class Workbook {
14531453
return true;
14541454
}
14551455
this.initRichData();
1456-
const maxFildId = this.findMaxFileId(/xl\/media\/image\d*.jpg/, /image(\d*)\.jpg/);
1456+
const maxFildId = this.findMaxFileId(/xl\/media\/image\d*\..*/, /image(\d*)\./);
1457+
const fileExtension = substitution.split('.').pop();
14571458
try {
14581459
substitution = this.imageToBuffer(substitution);
14591460
}
@@ -1465,12 +1466,12 @@ class Workbook {
14651466
throw error;
14661467
}
14671468
}
1468-
this.archive.file('xl/media/image' + maxFildId + '.jpg', this.toArrayBuffer(substitution), { binary: true, base64: false });
1469+
this.archive.file('xl/media/image' + maxFildId + '.' + fileExtension, this.toArrayBuffer(substitution), { binary: true, base64: false });
14691470
const maxIdRichData = this.findMaxId(this._relsrichValueRel, 'Relationship', 'Id', /rId(\d*)/);
14701471
const _rel = etree.SubElement(this._relsrichValueRel, 'Relationship');
14711472
_rel.set('Id', 'rId' + maxIdRichData);
14721473
_rel.set('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image');
1473-
_rel.set('Target', '../media/image' + maxFildId + '.jpg');
1474+
_rel.set('Target', '../media/image' + maxFildId + '.' + fileExtension);
14741475
const currentCountrdRichValue = this.rdrichvalue.get('count');
14751476
this.rdrichvalue.set('count', parseInt(currentCountrdRichValue) + 1);
14761477
const rv = etree.SubElement(this.rdrichvalue, 'rv');
@@ -1481,9 +1482,12 @@ class Workbook {
14811482
secondV.text = "5";
14821483
const rel = etree.SubElement(this.richValueRel, 'rel');
14831484
rel.set("r:id", 'rId' + maxIdRichData);
1484-
const futureMetadataCount = this.metadata.find('futureMetadata').get('count');
1485-
this.metadata.find('futureMetadata').set('count', parseInt(futureMetadataCount) + 1);
1486-
const bk = etree.SubElement(this.metadata.find('futureMetadata'), 'bk');
1485+
const futureMetadata = this.metadata.findall('futureMetadata').find(function(fm) {
1486+
return fm.attrib.name === 'XLRICHVALUE';
1487+
});
1488+
const futureMetadataCount = futureMetadata.get('count');
1489+
futureMetadata.set('count', parseInt(futureMetadataCount) + 1);
1490+
const bk = etree.SubElement(futureMetadata, 'bk');
14871491
const extLst = etree.SubElement(bk, 'extLst');
14881492
const ext = etree.SubElement(extLst, 'ext');
14891493
ext.set("uri", "{3e2802c4-a4d2-4d8b-9148-e3be6c30e623}");
@@ -1493,7 +1497,10 @@ class Workbook {
14931497
this.metadata.find('valueMetadata').set('count', parseInt(valueMetadataCount) + 1);
14941498
const bk_VM = etree.SubElement(this.metadata.find('valueMetadata'), 'bk');
14951499
const rc = etree.SubElement(bk_VM, 'rc');
1496-
rc.set("t", "1");
1500+
const XLRICHVALUEMetaDataTypeIndex = this.metadata.find('metadataTypes').findall('metadataType').findIndex(function(el) {
1501+
return el.attrib.name === "XLRICHVALUE";
1502+
});
1503+
rc.set("t", `${XLRICHVALUEMetaDataTypeIndex + 1}`);
14971504
rc.set("v", valueMetadataCount);
14981505
cell.set("t", "e");
14991506
cell.set("vm", parseInt(currentCountrdRichValue) + 1);

test/crud-test.ts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,121 @@ describe("CRUD operations", function() {
12531253
});
12541254
});
12551255

1256+
it("Insert imageincells table with metadata already init", function(done) {
1257+
fs.readFile(path.join(__dirname, 'templates', 'test-insert-images_in_cell_with_metadata.xlsx'), function(err, data) {
1258+
expect(err).toBeNull();
1259+
var option = {
1260+
imageRootPath : path.join(__dirname, 'templates', 'dataset')
1261+
}
1262+
var t = new XlsxTemplate(data, option);
1263+
var imgB64 = 'iVBORw0KGgoAAAANSUhEUgAAALAAAAA2CAYAAABnXhObAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAUjSURBVHhe7ZtbyGVjGMfXlmmccpqRcYgZmQsTMeVYQiJzozEYJRHCcCUaNy5kyg3KhUNEhjSRbwipIcoF0pRpxiFiLsYUIqcoZ8b2/6/1vKtnv3u9+/smuXjW/v/qv593PetZa+/17f9617vetb9BVVVDSIiQ7GFRiJC0PfBwOGRbiBAMBoPat+qBRWhkYBEaGViERgYWoZGBRWhkYBEaGViERgYWoZGBRWhkYBEaGViERgYWoZGBRWhkYBEaGViERgYWoenND9oHg8EFCOdBPJ57cDzfWf5MhLPZBr9AL2LdzmZxFNTui3AdtF+dqKqtqH3F2iOg9g6EVLcFdTPW7gT1CxAuhE6FFkG/Ql9Cm7HtC4gtqL0S4ehmaRzU32XNiWA/VyGcDGGT4c11sifg2Np/hWODB8iXsAJ3p2OBznL5rS5Pfey38wJPuzpqe6HuXFdDfdRVlwRo9r+stkvboYWu/ifLlzTP7z8XOBZ63mqTDuyqjap0XNMwhGCvStjjkeNw9q6ydgtyCxEub5Za5lnMWW0xsQzbn2btEZBfh0DtWSeq6h3oQeghaBMTYCl0UtMc4U/obegN6FXoJWgGXyBPhk7wfrcgfAJdXCemgNrJ3t0RBUo98KeW+wCiIdjmMCLfnpdYNrw+y+us9ltb/6FFisOWvO4Ut/4HaHWh5j7odJdLPfAXvnYuAk/Ztuuhn61NqQcOzt/QM02zWome6gBrJzj2Jey9imC7lQjsrcn1FsmlFj33WiS34Q+/0dotyL0L3QptttR/hT32cuzvWkQec6+ZNgNvaJo1ay3SlLyxOr5Zqm6wWKI1qpluW7NULcF+zrE29zkfId08sid/3Nq7BfazwMvSRfA+j0Lv2eIui71lqgyML/Z1xO+bxepqi+RGizTAW9Ycw0yZxr+8VJP7LZJLLJJjLBIOY2qwj1XQRtOM6VmIMxM5R0CcTWmFunRSzAX1wD0ifZnpMn4kzHCita+xyLEoKX3xNC9NTB7mCwz/ZL3U4A18sEWSThpyCMRenOL+qMsgfxNXD/IKTFqXox64RyRTcqossQ4mvsna5AmLacYinxv3sw9/YNvlFNpp/HoYlldY+2uLhLMMiTchvifFGYlJcJ6YJ0IrnDDcfq703sCkvpsDfAkrMNssxGsut8Ny1O8W2xkHQPOxsdPleOPGxmx6zG3Dyz4bfI9FKe/WP2DrqRUu/6PldnsWwgvwgU3av2YhguOHBX42IA0J/Fj2N4se3/tOwg8j0qwH3+POpjnC/z1G1RCipzxn0eMfBU8y8C70AINcyKeT4iAMIy6y9u3QN02zWoP8y9D50OHQMuTOaFaVQd0JuWxVJ1i/N7SUwqI/QY5CbjG0vy33hrorBmPddCSB2YYQm7L69y3ftW6L5eshBFhiy9R6X5sEOD+caja4PG8QeROX1pXUNYQoaX6qzQV4JcnrvTo/fzSl45nWHpj4YUT+Q5y8B+YPhRJ8nDsG/qjMf9UsVVdYZJ43hpxS4+NjPsHL4Xj8EdTxUXEi7adE/Q0WKD5mNno1rOClr7FzcxkMDS6P+zDiWNIsQg3yeyHHG6kRmGcsrfP50r5zZqvD+sUIh0L8ZdznqONj4zHSZ+ui6/N6sG2xY8K2/1gzNDjG2re9MrCYHpKBp3kIIXqADCxCIwOL0MjAIjQysAiNDCxCIwOL0MjAIjQysAiNDCxCIwOL0MjAIjQysAiNDCxCIwOL0MjAIjQysAhN+x8ZQkREPbAITFX9C5ozpqaetbGcAAAAAElFTkSuQmCC';
1264+
1265+
t.substitute('table_image_in_cell', {
1266+
imgArray : [
1267+
{filename : imgB64},
1268+
{filename : imgB64},
1269+
{filename : imgB64},
1270+
],
1271+
someText : "Hello ImageInCell",
1272+
});
1273+
var newData = t.generate();
1274+
try {
1275+
// Verify richData files
1276+
var richDataFile = etree.parse(t.archive.file("xl/richData/_rels/richValueRel.xml.rels").asText()).getroot();
1277+
expect(richDataFile.findall("Relationship").length).toEqual(4);
1278+
1279+
var rdrichvalueFile = etree.parse(t.archive.file("xl/richData/rdrichvalue.xml").asText()).getroot();
1280+
expect(rdrichvalueFile.findall("rv").length).toEqual(4);
1281+
expect(parseInt(rdrichvalueFile.attrib.count)).toEqual(4);
1282+
1283+
var richValueRelFile = etree.parse(t.archive.file("xl/richData/richValueRel.xml").asText()).getroot();
1284+
expect(richValueRelFile.findall("rel").length).toEqual(4);
1285+
1286+
// Verify metadata.xml file
1287+
var metadataFile = etree.parse(t.archive.file("xl/metadata.xml").asText()).getroot();
1288+
1289+
// Verify that metadataTypes still contains 2 types (XLDAPR and XLRICHVALUE)
1290+
var metadataTypes = metadataFile.find('metadataTypes');
1291+
expect(parseInt(metadataTypes.attrib.count)).toEqual(2);
1292+
var metadataTypesList = metadataTypes.findall('metadataType');
1293+
expect(metadataTypesList.length).toEqual(2);
1294+
expect(metadataTypesList[0].attrib.name).toEqual('XLDAPR');
1295+
expect(metadataTypesList[1].attrib.name).toEqual('XLRICHVALUE');
1296+
1297+
// Verify that XLRICHVALUE is at index 1 (the second type)
1298+
var xlrichvalueIndex = -1;
1299+
for (var i = 0; i < metadataTypesList.length; i++) {
1300+
if (metadataTypesList[i].attrib.name === 'XLRICHVALUE') {
1301+
xlrichvalueIndex = i;
1302+
break;
1303+
}
1304+
}
1305+
expect(xlrichvalueIndex).toEqual(1);
1306+
1307+
// Verify futureMetadata - there should be 2 (XLDAPR and XLRICHVALUE)
1308+
var futureMetadataList = metadataFile.findall('futureMetadata');
1309+
expect(futureMetadataList.length).toEqual(2);
1310+
1311+
// Find the XLRICHVALUE futureMetadata
1312+
var xlrichvalueFutureMetadata = null;
1313+
var xldaprFutureMetadata = null;
1314+
for (var i = 0; i < futureMetadataList.length; i++) {
1315+
if (futureMetadataList[i].attrib.name === 'XLRICHVALUE') {
1316+
xlrichvalueFutureMetadata = futureMetadataList[i];
1317+
} else if (futureMetadataList[i].attrib.name === 'XLDAPR') {
1318+
xldaprFutureMetadata = futureMetadataList[i];
1319+
}
1320+
}
1321+
1322+
// Verify that XLDAPR was not modified (still 1 element)
1323+
expect(xldaprFutureMetadata).not.toBeNull();
1324+
expect(parseInt(xldaprFutureMetadata.attrib.count)).toEqual(1);
1325+
expect(xldaprFutureMetadata.findall("bk").length).toEqual(1);
1326+
1327+
// Verify that XLRICHVALUE was updated (1 existing + 3 new = 4)
1328+
expect(xlrichvalueFutureMetadata).not.toBeNull();
1329+
expect(parseInt(xlrichvalueFutureMetadata.attrib.count)).toEqual(4);
1330+
var xlrichvalueBkList = xlrichvalueFutureMetadata.findall("bk");
1331+
expect(xlrichvalueBkList.length).toEqual(4);
1332+
1333+
// Verify that the i indexes are correct (0, 1, 2, 3)
1334+
for (var i = 0; i < xlrichvalueBkList.length; i++) {
1335+
var rvb = xlrichvalueBkList[i].find(".//xlrd:rvb");
1336+
expect(rvb).not.toBeNull();
1337+
expect(rvb.attrib.i).toEqual(i.toString());
1338+
}
1339+
1340+
// Verify cellMetadata (should remain at 1)
1341+
var cellMetadata = metadataFile.find('cellMetadata');
1342+
expect(parseInt(cellMetadata.attrib.count)).toEqual(1);
1343+
expect(cellMetadata.findall("bk").length).toEqual(1);
1344+
1345+
// Verify valueMetadata (1 existing + 3 new = 4)
1346+
var valueMetadata = metadataFile.find('valueMetadata');
1347+
expect(parseInt(valueMetadata.attrib.count)).toEqual(4);
1348+
var valueMetadataBkList = valueMetadata.findall("bk");
1349+
expect(valueMetadataBkList.length).toEqual(4);
1350+
1351+
// Verify that t and v attributes are correct in valueMetadata
1352+
// The first element (existing) should have t="2" v="0"
1353+
expect(valueMetadataBkList[0].find("rc").attrib.t).toEqual("2");
1354+
expect(valueMetadataBkList[0].find("rc").attrib.v).toEqual("0");
1355+
1356+
// The new elements should have t="2" (xlrichvalueIndex + 1 = 1 + 1 = 2) and increasing v
1357+
for (var i = 1; i < valueMetadataBkList.length; i++) {
1358+
var rc = valueMetadataBkList[i].find("rc");
1359+
expect(rc.attrib.t).toEqual("2"); // xlrichvalueIndex (1) + 1 = 2
1360+
expect(rc.attrib.v).toEqual(i.toString());
1361+
}
1362+
1363+
fs.writeFileSync('test/output/insert_imageincell_table_with_metadata.xlsx', newData, 'binary');
1364+
done();
1365+
} catch (err) {
1366+
done(err);
1367+
}
1368+
});
1369+
});
1370+
12561371
it("Insert some format of image", function(done) {
12571372
fs.readFile(path.join(__dirname, "templates", "test-insert-images.xlsx"), function(err, data) {
12581373
expect(err).toBeNull();
14.4 KB
Binary file not shown.

0 commit comments

Comments
 (0)