Documentation for PDFColumns
By Stephen Joys Aug 11th 2020PDF Columns is wrapper for jsPDF that is still written as code but has an easier document formating system to produce clean PDF documents with autobuilt columns, styles and images. while jsPDF does not allow for zorder of printing, this app can work around it and print images and background colors behind text
In this first example, let's create a new document, add a background image, add some text and save.
//starting document
let pdf = new PDFColumns("filename");
await PDFLoadImage(pdf,'background',"back_image.png");
await PDFLoadImage(pdf,'robocat',"doraemon.png");
pdf.dim.left= 14; //adjust the margins before adding pages
//add background before loading first page;
// add a page with auto-numbering and background
pdf.newPage();
// writes following main page dimensions set in pdf.dim
pdf.nline("here is some text");
pdf.nline("and some more");
pdf.cimage("robocat");
pdf.save(); //opens download dialog for user to get the file
Adding columns to document
Next we can add down-flowing columns to the document: this code creates a new PDFColumns document and uses the col() or 'columns' to generate two side-by-side columns for writing
let pdf = new PDFColumns("filename");
pdf.newPage(); //do variable loading as above
pdf.col(2); // create two side by side columns of equal size total 100% of print range
pdf.nline("write text in first column");
pdf.nline("keep writing next line down on same column");
pdf.next(); //swaps to next col in this group
pdf.nline("write text in the second column at its starting point");
pdf.next(); //cycle back to the first column);
pdf.end();
pdf.save();
Nested columns
We can also nest columns infinitely. in this example we will create a set of 3 columns in the first large column. Some flags are sent with the text to allign the text in the middle
let pdf = new PDFColumns("filename",{align:"center"});
pdf.newPage();
pdf.nline("document title at top of page");
pdf.col(2); // create two side by side columns of equal size total 100% of print range
pdf.nline("below are nested columns");
pdf.col(3,[2,5,5]); // 3 columns spliting parent column space in ratio 2,5,5
pdf.nline("1st small",{align:"center"});
pdf.nline("data 1",{align:"center"});
pdf.next();
pdf.nline("2nd column",{align:"center"});
pdf.nline("data 2",{align:"center"});
pdf.next();
pdf.nline("3rd Column",{align:"center"});
pdf.nline("data 3",{align:"center"});
pdf.end();
pdf.next(); //back to top columns set
//lets make a grid using arrays
pdf.col(4);
for(let i = 0;i<4;i++){
for(let j = 0;j<4;j++){
pdf.nline(""+(i*4+j+1));
pdf.next();
}
}
pdf.end();
pdf.end();
pdf.save();
Styles
Next the formatting avaliable for jsPDF, like text color, font, size, line color, etc. has been organized into 3 functions that can save collections of styles by name and apply new or saved styles quickly
// create a style but dont apply it, simply save it as default to be accessed later
// by virtue of being the first one given by the user, this is set as default
pdf.addStyle({name:"mytext",font:"verdana",fontsize:10,fontstyle:"bold", color:"#000000"});
pdf.style(); //applies last kept style as single 'previous style' (no full history)
pdf.nline("style();");
pdf.style("mytext"); //applies named style saved previously, keeps this style as fallback
pdf.nline("mytext");
pdf.style({color:"#0000FF"},1); // applies new style, doesn't save as fallback
pdf.nline("red");
pdf.style(); //returns to previous
pdf.nline("black like mytext again");
pdf.style({name:"newstyle", {color:"#0000FF"}); //saves, applies, and saves as fallback
pdf.style({fontsize:14}); // applies, and saves as fallback
// applying styles does nothing to keys not present, so clearing styles means
// applying a style with all keys accounted for (user could make a detailed style called "default")
// and apply that to clean out the odd spacing or colors
pdf.nline("this text is altered by last styles applied");
Border and Fill
Another type of style tag are border and fillcolor, that affects currently active column and unlike jsPDF will be correctly applied behind flowing text and images after everything is written
pdf.col(2);
pdf.style({border:"#00FF00"}); // this style is fixed onto the active column
pdf.nline("this column will be bordered by a colored box");
pdf.next();
pdf.style({fillcolor:"#FF0000",color:"0000FF"});//fill and change text color
pdf.nline("this column will be filled in with color");
pdf.end();
Page loading
Pages are added when needed and their pagenumber is added (see this.pagenumber.x , y for location)
let pdf = new PDFColumns("filename");
var test = await PDFLoadImage(pdf,'background',"back_image.png");
pdf.pagecounter.y-=10; // can fix x and y to appropriate location
pdf.dim.left+=5;
pdf.dim.bottom+=5;
pdf.newPage();
pdf.col(2);
for(let c = 0;c<2;c++){
for(let i = 0;i<200;i++)
pdf.nline("This is column "+(c+1)+" and line "+i);
pdf.next();
}
pdf.end();
pdf.save();
Building tables
Here are a few examples where we build tables for objects and object arrays
function example7generator(pdf, data){
pdf.col(1);//wrapper
pdf.style("table");//creates full table border
let keys =null;
//passed array of objects
if (Array.isArray(data)){
//gather all keys from the objects within the data array
keys = Object.keys(data[0]);
let filter_keys =[];
data.forEach(row => { //find kes that arent in current list then concat them
filter_keys = new Set(keys);
keys = keys.concat(Object.keys(row).filter(key => !filter_keys.has(key)));
});
//passed single object
}else{
keys = Object.keys(data);
}
pdf.col(keys.length);//print header for keys table
keys.forEach(head => {pdf.style("tableheader");pdf.nline(head); pdf.next()});
pdf.end();//end header
for(let i = 0;i<(Array.isArray(data)?data.length:1);i++){
pdf.col(keys.length);//by starting and ending columns each row we can have row borders,otherwise omit
keys.forEach(head => { pdf.style("tableline"+(i%2));
pdf.nline((Array.isArray(data)?data[i][head]:data[head]));
pdf.next();
});
pdf.end();
}
pdf.end();//wrapper
}
// start pdf and add some table styles that show borders and background-color (fillcolor)
let pdf = new PDFColumns("filename");
pdf.addStyle({name:"table",border:"#000000",font:"verdana"});
pdf.addStyle({name:"tableheader",fillcolor:"#DDDDDD",fontstyle:"bold"});
pdf.addStyle({name:"tableline0",fillcolor:"#ffffff",fontstyle:"normal"});
pdf.addStyle({name:"tableline1",fillcolor:"#f4f4f4"});
pdf.newPage(); //do variable loading as above
// lets put a single object through a column generator
let data = {name:"BMW #005", type:"car", cost:"$36,000", color:"black"};
example7generator(pdf,data);
pdf.nline();
// Now lets make an array of objects to pass through
// a column generator
data= [{name:"horse",color:"brown",speed:"fastest",size:"huge"},
{name:"dog",color:"white",speed:"fast",size:"big"},
{name:"cat",color:"orange",speed:"meh",size:"small"},
{name:"mouse",color:"grey",speed:"slight",size:"tiny"}];
example7generator(pdf,data);//same as above
pdf.nline();
//simple generator for object arrays
let keys =Object.keys(data[0]);
pdf.col(1);//wrapper
pdf.style("table");//creates full table border
pdf.col(keys.length);//animal, size, color etc...
//print header
keys.forEach(head => {pdf.style("tableheader");pdf.nline(head); pdf.next()});
//write rows
for(let i = 0;i { pdf.style("tableline"+(i%2));
pdf.nline(data[i][head]);
pdf.next()});
}
pdf.end();
pdf.end();//wrapper*/
pdf.nline();
//Last lets fee some data from the styles we have given the PDFColumns pdf
example7generator(pdf,pdf.styles);
pdf.save();
Inserting Pictures
pictures loaded in can be placed on page with cimage and cbimage (which appends flag background to flags) Pictures can be back or inline with text, be given own size or "auto" to scale with column size
let pdf = new PDFColumns("filename");
await PDFLoadImage(pdf,'robocat',"doraemon.png");
// add a page with auto-numbering and background
pdf.newPage();
pdf.nline();
pdf.col(3,[3,5,3]);
pdf.next();
pdf.style({border:"#FF0000"});
pdf.cbimage('robocat');
pdf.nline("This cat was a robot sent to the past to protect and teach an important scientist before he grows up; sent by the man himself from the future",{wrap:true, align:"center"});
pdf.end();
pdf.col(3);
// fill with color and with background image
pdf.style({fillcolor:"#FF0000"});
pdf.cbimage('robocat');
pdf.nline("write over",{align:"center"});
pdf.next();
//add border around, and image is inline with text
pdf.style({border:"#00FF00"});
pdf.cimage('robocat');
pdf.nline("write under",{align:"center"});
pdf.next();
//image has been centered (point of drawing) with background color
pdf.style({fillcolor:"#0000FF"});
pdf.cimage('robocat',{height:40, alignx:"center", aligny:"center"});
pdf.nline("write under");
pdf.save();