Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions lib/stream/xlsx/workbook-writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const ContentTypesXform = require('../../xlsx/xform/core/content-types-xform');
const AppXform = require('../../xlsx/xform/core/app-xform');
const WorkbookXform = require('../../xlsx/xform/book/workbook-xform');
const SharedStringsXform = require('../../xlsx/xform/strings/shared-strings-xform');
const DrawingXform = require('../../xlsx/xform/drawing/drawing-xform');

const WorksheetWriter = require('./worksheet-writer');

Expand Down Expand Up @@ -45,6 +46,7 @@ class WorkbookWriter {
this.zipOptions = options.zip;

this.media = [];
this.drawings = [];
this.commentRefs = [];

this.zip = Archiver('zip', this.zipOptions);
Expand Down Expand Up @@ -99,6 +101,7 @@ class WorkbookWriter {
await this.promise;
await this.addMedia();
await this._commitWorksheets();
await this.addDrawings();
await Promise.all([
this.addContentTypes(),
this.addApp(),
Expand Down Expand Up @@ -219,6 +222,7 @@ class WorkbookWriter {
sharedStrings: this.sharedStrings,
commentRefs: this.commentRefs,
media: this.media,
drawings: this.drawings,
};
const xform = new ContentTypesXform();
const xml = xform.toXml(model);
Expand Down Expand Up @@ -249,6 +253,25 @@ class WorkbookWriter {
);
}

addDrawings() {
return Promise.all(
this.drawings.map(drawing => {
const drawingXform = new DrawingXform();
const relsXform = new RelationshipsXform();
if (drawing) {
drawingXform.prepare(drawing, {});
const xml = drawingXform.toXml(drawing);
const xmlRels = relsXform.toXml(drawing.rels);
return [
this.zip.append(xml, {name: `xl/drawings/${drawing.name}.xml`}),
this.zip.append(xmlRels, {name: `xl/drawings/_rels/${drawing.name}.xml.rels`}),
];
}
return null;
}).flat().filter(Boolean)
);
}

addApp() {
return new Promise(resolve => {
const model = {
Expand Down
52 changes: 52 additions & 0 deletions lib/stream/xlsx/worksheet-writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const PictureXform = require('../../xlsx/xform/sheet/picture-xform');
const ConditionalFormattingsXform = require('../../xlsx/xform/sheet/cf/conditional-formattings-xform');
const HeaderFooterXform = require('../../xlsx/xform/sheet/header-footer-xform');
const RowBreaksXform = require('../../xlsx/xform/sheet/row-breaks-xform');
const DrawingXform = require('../../xlsx/xform/drawing/drawing-xform');
const Image = require('../../doc/image');

// since prepare and render are functional, we can use singletons
const xform = {
Expand All @@ -49,6 +51,7 @@ const xform = {
pageSeteup: new PageSetupXform(),
autoFilter: new AutoFilterXform(),
picture: new PictureXform(),
drawing: new DrawingXform(),
conditionalFormattings: new ConditionalFormattingsXform(),
headerFooter: new HeaderFooterXform(),
rowBreaks: new RowBreaksXform(),
Expand Down Expand Up @@ -244,6 +247,7 @@ class WorksheetWriter {
this._writePageMargins();
this._writePageSetup();
this._writeBackground();
this._writeDrawings();
this._writeHeaderFooter();
this._writeRowBreaks();

Expand Down Expand Up @@ -470,6 +474,19 @@ class WorksheetWriter {
}

// =========================================================================
addImage(imageId, range) {
const model = {
type: 'image',
imageId,
range,
};
const im = new Image(this, model);
this._media.push(im);
}

getImages() {
return this._media.filter(m => m.type === 'image');
}

addBackgroundImage(imageId) {
this._background = {
Expand Down Expand Up @@ -695,6 +712,41 @@ class WorksheetWriter {
}
}

_writeDrawings() {
if (this._media.length) {
const images = this.getImages();
const lastDrawingId = this.workbook.drawings.length + 1;
const drawingId = this._sheetRelsWriter.addMedia({
Target: `../drawings/drawing${lastDrawingId}.xml`,
Type: RelType.Drawing,
});
const drawing = {
rId: drawingId,
name: `drawing${lastDrawingId}`,
rels: images.map((img, index) => {
const image = this.workbook.getImage(img.imageId);
return {
Id: `rId${index + 1}`,
Type: RelType.Image,
Target: `../media/${image.name}`,
};
}),
anchors: images.map((img, index) => {
return {
picture: {
rId: `rId${index+1}`,
},
range: img.range,
};
}),
};
this.workbook.drawings.push(drawing);
xmlBuffer.reset();
xmlBuffer.addText(`<drawing r:id="${drawing.rId}" />`);
this.stream.write(xmlBuffer);
}
}

_writeLegacyData() {
if (this.hasComments) {
xmlBuffer.reset();
Expand Down
1 change: 1 addition & 0 deletions lib/xlsx/rel-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
Theme: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme',
Hyperlink: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
Image: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
Drawing: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing',
CoreProperties:
'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
ExtenderProperties:
Expand Down
3 changes: 2 additions & 1 deletion lib/xlsx/xform/core/content-types-xform.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ class ContentTypesXform extends BaseXform {
PartName: name,
ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml',
});

});

xmlStream.leafNode('Override', {
PartName: '/xl/theme/theme1.xml',
ContentType: 'application/vnd.openxmlformats-officedocument.theme+xml',
Expand Down
29 changes: 29 additions & 0 deletions spec/integration/worksheet-xlsx-writer.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const path = require('path');
const testutils = require('../utils/index');

const ExcelJS = verquire('exceljs');
Expand Down Expand Up @@ -535,4 +536,32 @@ describe('WorksheetWriter', () => {
expect(ws.rowBreaks.length).to.equal(2);
});
});

describe('Images/Drawings', () => {
it.skip('add images', async () => {
// const wb = new ExcelJS.stream.xlsx.WorkbookWriter();
const filename = path.join(__dirname, 'test.xlsx');
const wb = new ExcelJS.stream.xlsx.WorkbookWriter({filename, useStyles: true, useSharedStrings: true});
const ws1 = wb.addWorksheet('foo');
const ws2 = wb.addWorksheet('bar');

const imageId1 = wb.addImage({
filename: path.join(__dirname, 'data/image.png'),
extension: 'png',
});
const imageId2 = wb.addImage({
filename: path.join(__dirname, 'data/bubbles.jpg'),
extension: 'jpg',
});
ws1.addImage(imageId1, {
tl: {col: 0.25, row: 0.7},
ext: {width: 160, height: 60},
});
ws2.addImage(imageId2, 'C1:F10');

ws1.commit();
ws2.commit();
await wb.commit();
});
});
});
42 changes: 42 additions & 0 deletions test/test-stream-addImage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const path = require('path');
const Excel = require('../lib/exceljs.nodejs');
const HrStopwatch = require('./utils/hr-stopwatch');

const filename = process.argv[2];

const wb = new Excel.stream.xlsx.WorkbookWriter({filename});
const ws1 = wb.addWorksheet('Foo');
const imageId1 = wb.addImage({
filename: path.join(__dirname, 'data/image2.png'),
extension: 'png',
});
const imageId2 = wb.addImage({
filename: path.join(__dirname, 'data/bubbles.jpg'),
extension: 'jpg',
});

ws1.addImage(imageId1, {tl: {col: 0.25, row: 0.7},
ext: {width: 160, height: 60}});

ws1.addImage(imageId2, 'C1:F10');

const ws2 = wb.addWorksheet('Fooo2');
ws2.addImage(imageId1, 'A1:B4');
const imageId3 = wb.addImage({
filename: path.join(__dirname, 'data/image2.png'),
extension: 'png',
});
ws2.addImage(imageId3, 'B4:D10');
const stopwatch = new HrStopwatch();
stopwatch.start();

wb.commit()
.then(() => {
const micros = stopwatch.microseconds;
console.log('Done.');
console.log('Time taken:', micros);
})
.catch(error => {
console.log(error.message);
});