This sample shows how to create a tagged PDF using the Expense Analysis Report sample as a base.
The sample uses the info.title, tagged, displayTitle and lang properties to satisfy the basic Tagged PDF requirements when creating the instance of the PdfDocument class.
The sample uses the tag method to create tags and mark content and the addTag method to add tags to the logical document tree. The artifact method is used to mark decorative content as artifacts.
Note: Tagged PDF requires document version 1.4 or higher.
import 'bootstrap.css';
import '@mescius/wijmo.styles/wijmo.css';
import './styles.css';
//
import * as wijmo from '@mescius/wijmo';
import * as grid from '@mescius/wijmo.grid';
import * as chart from '@mescius/wijmo.chart';
import '@mescius/wijmo.chart.render';
import * as pdf from '@mescius/wijmo.pdf';
import * as gridPdf from '@mescius/wijmo.grid.pdf';
//
import { getEmployee } from './data';
//
document.readyState === 'complete' ? init() : window.onload = init;
//
function init() {
let employee = getEmployee();
//
let flexGrid = new grid.FlexGrid('#flexGrid', {
autoGenerateColumns: false,
headersVisibility: grid.HeadersVisibility.Column,
allowMerging: grid.AllowMerging.All,
itemsSource: employee.expenses.items,
columns: [
{ header: 'Date', binding: 'date', format: 'd', minWidth: 80 },
{ header: 'Hotel', binding: 'hotel', format: 'c' },
{ header: 'Transport', binding: 'transport', format: 'c', minWidth: 80 },
{ header: 'Meal', binding: 'meal', format: 'c' },
{ header: 'Fuel', binding: 'fuel', format: 'c' },
{ header: 'Misc', binding: 'misc', format: 'c' }
]
});
//
let flexPie = new chart.FlexPie('#flexPie', {
itemsSource: ((totals) => [
{ name: 'Hotel', value: totals.hotel },
{ name: 'Transport', value: totals.transport },
{ name: 'Meal', value: totals.meal },
{ name: 'Fuel', value: totals.fuel },
{ name: 'Misc', value: totals.misc }
])(employee.expenses.totals),
binding: 'value',
bindingName: 'name',
innerRadius: 0.75,
dataLabel: {
content: '{value:c1}',
position: chart.PieLabelPosition.Inside
}
});
//
document.querySelector('#btnExport').addEventListener('click', () => {
let doc = new pdf.PdfDocument({
info: {
title: 'Expense Analysis Report'
},
tagged: true,
displayTitle: true,
lang: 'en-US',
version: pdf.PdfVersion.v1_5,
// The header will be automatically marked as a pagination artifact.
header: {
declarative: {
text: 'Expense Analysis Report',
font: new pdf.PdfFont('times', 12),
brush: '#bfc1c2'
}
},
lineGap: 2,
pageSettings: {
margins: {
left: 12,
right: 12,
top: 12,
bottom: 12
}
},
ended: (_, args) => pdf.saveBlob(args.blob, 'FlexGrid.pdf')
});
//
drawText(doc);
//
drawEmployee(doc, flexGrid, flexPie, employee, () => {
doc.artifact(() => drawWatermark(doc), { type: pdf.PdfArtifactType.Pagination });
doc.end();
});
});
}
//
function drawText(doc) {
doc.addTag(doc.tag(pdf.PdfTagType.H1, () => {
doc.drawText('What is an expense report?', undefined, undefined, {
font: new pdf.PdfFont('times', 20, 'normal', 'bold')
});
}));
//
doc.addTag(doc.tag(pdf.PdfTagType.P, () => {
doc.drawText(`An expense report is a form of document that contains all the expenses that an
individual has incurred as a result of the business operation. For example, if the owner of a business
travels to another location for a meeting, the cost of travel, the meals, and all other expenses that
he/she has incurred may be added to the expense report.`.replace(/\n/g, ''));
}));
}
//
function drawEmployee(doc, flexGrid, flexPie, employee, done) {
let expenses = employee.expenses.items.sort((a, b) => a.date.getTime() - b.date.getTime()), minDate = expenses[0].date, maxDate = expenses[expenses.length - 1].date, bold = new pdf.PdfFont('times', 10, 'normal', 'bold');
//
doc.moveDown(2);
//
doc.addTag(doc.tag(pdf.PdfTagType.P, () => {
doc.drawText('Name: ', undefined, undefined, { font: bold, continued: true });
doc.drawText(employee.name);
}));
//
doc.addTag(doc.tag(pdf.PdfTagType.P, () => {
doc.drawText('From: ', undefined, undefined, { font: bold, continued: true });
doc.drawText(wijmo.changeType(minDate, wijmo.DataType.String, 'd'));
}));
//
doc.addTag(doc.tag(pdf.PdfTagType.P, () => {
doc.drawText('To: ', undefined, undefined, { font: bold, continued: true });
doc.drawText(wijmo.changeType(maxDate, wijmo.DataType.String, 'd'));
}));
//
doc.moveDown(2);
let y = doc.y;
//
doc.addTag(doc.tag(pdf.PdfTagType.P, () => {
doc.drawText('Expense details:', 0, y);
}));
//
gridPdf.FlexGridPdfConverter.draw(flexGrid, doc, doc.width * 0.5, null, {
styles: {
cellStyle: {
backgroundColor: '#ffffff',
borderColor: '#c6c6c6'
},
altCellStyle: {
backgroundColor: '#f9f9f9'
},
groupCellStyle: {
font: { weight: 'bold' },
backgroundColor: '#dddddd'
},
headerCellStyle: {
backgroundColor: '#eaeaea'
}
}
});
//
flexPie.saveImageToDataUrl(chart.ImageFormat.Png, (url) => {
doc.addTag(doc.tag(pdf.PdfTagType.Figure, [
doc.tag(pdf.PdfTagType.Caption, () => {
doc.drawText('Total expenses by category:', doc.width * 0.5 + 20, y);
}),
() => {
doc.drawImage(url, doc.width * 0.5 + 20, doc.y, { width: doc.width * 0.5 - 20 });
}
], { actual: 'The chart' }));
// Finish the document.
done();
});
}
//
function drawWatermark(doc) {
let docX = doc.x, docY = doc.y, font = new pdf.PdfFont('times', 120), color = wijmo.Color.fromRgba(59, 59, 109, 0.05), pgc = new wijmo.Point(doc.width / 2, doc.height / 2), text = 'Wijmo', offs = 10;
//
doc.x = 0;
doc.y = 0;
//
let sz = doc.measureText(text, font), szCx = sz.size.width / 2, szCy = sz.size.height / 2;
//
doc.saveState();
//
doc.rotate(45, pgc);
//
doc.drawText(text, pgc.x - szCx, pgc.y - szCy, {
font: font,
brush: color,
baseline: pdf.PdfTextBaseline.Top
});
//
doc.paths
.rect(pgc.x - szCx - offs, pgc.y - szCy - offs, sz.size.width + 2 * offs, sz.size.height - offs)
.stroke(new pdf.PdfPen(color, 10));
//
doc.restoreState();
//
doc.x = docX;
doc.y = docY;
}
Submit and view feedback for