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.
This example uses React.
loading...import 'bootstrap.css';
import '@mescius/wijmo.styles/wijmo.css';
import ReactDOM from 'react-dom/client';
import React, { useRef, useState } from 'react';
import useEvent from 'react-use-event-hook';
import '@mescius/wijmo.chart.render';
import * as wjcCore from '@mescius/wijmo';
import * as wjcGrid from '@mescius/wijmo.react.grid';
import * as wjChart from '@mescius/wijmo.chart';
import * as wjChartModule from '@mescius/wijmo.react.chart';
import * as gridPdf from '@mescius/wijmo.grid.pdf';
import * as pdf from '@mescius/wijmo.pdf';
import './app.css';
import { getEmployee } from './data';
function App() {
const [employee, setEmployee] = useState(getEmployee());
const [totals, setTotals] = useState([
{ name: 'Hotel', value: employee.expenses.totals.hotel },
{ name: 'Transport', value: employee.expenses.totals.transport },
{ name: 'Meal', value: employee.expenses.totals.meal },
{ name: 'Fuel', value: employee.expenses.totals.fuel },
{ name: 'Misc', value: employee.expenses.totals.misc }
]);
const flexGridRef = useRef(null);
const flexPieRef = useRef(null);
const employeeRef = useRef(null);
const initializeGrid = useEvent((ctl) => {
flexGridRef.current = ctl;
});
const initializePie = useEvent((ctl) => {
flexPieRef.current = ctl;
});
const exportPDF = () => {
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: (sender, args) => pdf.saveBlob(args.blob, 'FlexGrid.pdf')
});
drawText(doc);
drawEmployee(doc, flexGridRef.current, flexPieRef.current, employee, () => {
doc.artifact(() => drawWatermark(doc), { type: pdf.PdfArtifactType.Pagination });
doc.end();
});
};
const 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, ''));
}));
};
const 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(wjcCore.changeType(minDate, wjcCore.DataType.String, 'd'));
}));
//
doc.addTag(doc.tag(pdf.PdfTagType.P, () => {
doc.drawText('To: ', undefined, undefined, { font: bold, continued: true });
doc.drawText(wjcCore.changeType(maxDate, wjcCore.DataType.String, 'd'));
}));
//
doc.moveDown(2);
let y = doc.y;
//
doc.addTag(doc.tag(pdf.PdfTagType.P, () => {
doc.drawText('Expense details:', 0, y);
}));
y = doc.y;
//
gridPdf.FlexGridPdfConverter.draw(flexGrid, doc, doc.width * 0.5, undefined, {
styles: {
cellStyle: {
backgroundColor: '#ffffff',
borderColor: '#c6c6c6'
},
altCellStyle: {
backgroundColor: '#f9f9f9'
},
groupCellStyle: {
font: { weight: 'bold' },
backgroundColor: '#dddddd'
},
headerCellStyle: {
backgroundColor: '#eaeaea'
}
}
});
//
flexPie.saveImageToDataUrl(wjChart.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();
});
};
const drawWatermark = (doc) => {
let docX = doc.x, docY = doc.y, font = new pdf.PdfFont('times', 120), color = wjcCore.Color.fromRgba(59, 59, 109, 0.05), pgc = new wjcCore.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;
};
return (<main className="container-fluid">
{/* Export button */}
<button className="btn btn-default" onClick={exportPDF}>Export</button>
<div className="row">
<div className="col-lg-6 col-md-12">
{/* FlexGrid */}
<wjcGrid.FlexGrid className="grid" autoGenerateColumns={false} headersVisibility="Column" allowMerging="All" itemsSource={employee.expenses.items} initialized={initializeGrid}>
<wjcGrid.FlexGridColumn header="Date" binding="date" format="d" minWidth={80}/>
<wjcGrid.FlexGridColumn header="Hotel" binding="hotel" format="c"/>
<wjcGrid.FlexGridColumn header="Transport" binding="transport" format="c" minWidth={80}/>
<wjcGrid.FlexGridColumn header="Meal" binding="meal" format="c"/>
<wjcGrid.FlexGridColumn header="Fuel" binding="fuel" format="c"/>
<wjcGrid.FlexGridColumn header="Misc" binding="misc" format="c"/>
</wjcGrid.FlexGrid>
</div>
<div className="col-lg-6 col-md-12">
<wjChartModule.FlexPie binding="value" bindingName="name" innerRadius={0.75} initialized={initializePie} itemsSource={totals}>
<wjChartModule.FlexChartDataLabel content='{value:c1}'/>
</wjChartModule.FlexPie>
</div>
</div>
</main>);
}
const container = document.getElementById('app');
if (container) {
const root = ReactDOM.createRoot(container);
root.render(<App />);
}
Submit and view feedback for