ExpertPDF - How to know page number based on content in HTML - pdf

Suppose I have a HTML that have some heading & text like:
Heading 1
text......
Heading 2
text.....
Heading 3
text.....
Now I have to print this template in PDF, during print out, I have to add index page which actually refer page number with heading. Means print out should be like this.
Heading 1 ....... 1 [page number]
Heading 2 ....... 2
Heading 3 ....... 3
Heading 1
text......
Heading 2
text.....
Heading 3
text.....
So here I want to know, how to know page number based on text in HTML, like heading 1 belong to which page number & for others.
Any suggestion or idea really appreciated.

pdfConverter.PdfFooterOptions.PageNumberTextFontSize = 10;
pdfConverter.PdfFooterOptions.ShowPageNumber = true;
Its done inside the body of this method :-
private void AddFooter(PdfConverter pdfConverter)
{
string thisPageURL = HttpContext.Current.Request.Url.AbsoluteUri;
string headerAndFooterHtmlUrl = thisPageURL.Substring(0, thisPageURL.LastIndexOf('/')) + "/HeaderAndFooterHtml.htm";
//enable footer
pdfConverter.PdfDocumentOptions.ShowFooter = true;
// set the footer height in points
pdfConverter.PdfFooterOptions.FooterHeight = 60;
//write the page number
pdfConverter.PdfFooterOptions.TextArea = new TextArea(0, 30, "This is page &p; of &P; ",
new System.Drawing.Font(new System.Drawing.FontFamily("Times New Roman"), 10, System.Drawing.GraphicsUnit.Point));
pdfConverter.PdfFooterOptions.TextArea.EmbedTextFont = true;
pdfConverter.PdfFooterOptions.TextArea.TextAlign = HorizontalTextAlign.Right;
// set the footer HTML area
pdfConverter.PdfFooterOptions.HtmlToPdfArea = new HtmlToPdfArea(headerAndFooterHtmlUrl);
pdfConverter.PdfFooterOptions.HtmlToPdfArea.EmbedFonts = cbEmbedFonts.Checked;
}
See this page for more details
http://www.expertpdf.net/expertpdf-html-to-pdf-converter-headers-and-footers/

This is actually a pretty tricky problem which ExpertPDF would have to provide specific functionality to make possible.
My solution (not expertpdf) for this was to calculate the layout of the PDF first, get the text to be used in the index for each page and then calculate the layout of the index page/s. Then I'm able to number the pages (including the index pages) then update the page numbers in the index.. This is the only way to handle template pages which span multiple pages themselves, index text which wraps to take up more than a single line, and indexes which span multiple pages.

Create a TextElement
TextElement te = new TextElement(xPos, yPos, width, ""Page &p; of &P;"", footerFont);
footerTemplate.AddElement(te);
The library will automatically replace the &p; tokens.

Related

Multi page PDF from AppScript - How to insert page breaks? [duplicate]

I would like to programmatically set page breaks in my Google Spreadsheet before exporting to PDF, using Apps Script
It should be possible as you can manually set the page breaks when you print the Spreadsheet (https://support.google.com/docs/answer/7663148?hl=en)
I found that it's possible in Google Docs (https://developers.google.com/apps-script/reference/document/page-break) but they don't mention it on the sheet.
Is there a way to do it, even if it's a "hack"?
Talking about "hacks", you may try to capture HTTP request sent from the Spreadsheet to Google when you are trying to save a sheet as PDF by going to the developer tools - Network.
From this link you can get formatting parameter pc, which in my case looks like this:
[null,null,null,null,null,null,null,null,null,0,
[["1990607563"]],
10000000,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
43866.56179325232,
null,null,
[0,null,1,0,0,0,1,1,1,1,2,1,null,null,2,1],
["A4",0,6,1,[0.75,0.75,0.7,0.7]],
null,0,
[["1990607563",[[45,92],[139,139]],[[0,15]]]],0]
where:
[["1990607563",[[45,92],[139,139]],[[0,15]]]],0] // page breaks parameters
Note though that I used custom page breaks and landscape orientation, which are reflected in the response above.
Putting it all together, the following code does the trick:
function exportPDFtoGDrive (ssID, filename, source){
var source = "1990607563"
var dt = new Date();
var d = encodeDate(dt.getFullYear(),dt.getMonth(),dt.getDate(),dt.getHours(),dt.getMinutes(),dt.getSeconds());
var pc = [null,null,null,null,null,null,null,null,null,0,
[[source]],
10000000,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
d,
null,null,
[0,null,1,0,0,0,1,1,1,1,2,1,null,null,2,1],
["A4",0,6,1,[0.75,0.75,0.7,0.7]],
null,0,
[[source,[[45,92],[139,139]],[[0,15]]]],0];
var folder = DriveApp.getFoldersByName("FolderNameGoesHere").next();
var options = {
'method': 'post',
'payload': "a=true&pc="+JSON.stringify(pc)+"&gf=[]",
'headers': {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
'muteHttpExceptions': true
};
const esid = (Math.round(Math.random()*10000000));
const theBlob =
UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/"+ssID+"/pdf?id="+ssID+"&esid="+esid, options).getBlob();
folder.createFile(theBlob).setName(filename+".pdf");
}
function myExportPDFtoGDrive(){
var ss = SpreadsheetApp.openById('yourSpreadSheetID');
var sheet = ss.getSheetByName("NameGoesHere");
var filename = ss.getName()+" ["+sheet.getName()+"]";
exportPDFtoGDrive (ss.getId(),filename);
}
A more detailed explanation of the hack is available here
Export Google Sheets to PDF though in Russian only.
I use a work around. I adjust the page size by altering the row height to fit the paper size I want (A4).
When exporting to pdf google changes sizes to fit the width. I add up the size of the columns and then set the row heights accordingly. Numbers were chosen by trial and error.
var width = 0;
for(var z = 0; z < s4.getLastColumn(); z++){
width += s4.getColumnWidth(z+1);
}
var a4PageHeightPixels = 1050 * width / 800;
Because I wanted the rows all the same height I set the row height dividing my page height by the number of rows. Having ensured the last row was blank, I adjusted the last row to take up the rounding error.
rowHeight= Math.floor(a4PageHeightPixels/(numDataRows ));
lastRowHeight = a4PageHeightPixels - (numDataRows -1) * rowHeight;
s4.setRowHeights(pageFirstRow,numDataRows-1,rowHeight);
s4.setRowHeight(pageFirstRow+numDataRows-1,lastRowHeight);
(s4 is the sheet I am using)However, I would expect most people would simply want to insert a blank line at the bottom of each page and adjust its size to fit the pdf paper size.

pdf is created from google slide, but with the markers populated (via GAS)

The code below basically maps columns from a spreadsheet to a couple of markers I got on a google slide.
It generates copies of the google slide template, updates them with the row's data and I actually need it to be in pdf form to be emailed later.
The pdf files are created in the destination folder, with the right file names, but the markers within them are "empty". Later on, I will have to delete these google slide files, but the challenge here now is to have the pdf files correctly created.
Appreciate your time.
function mailMerge(templateID,ssID, sheetName, mapped, fileNameData, emailCol, rowLen = "auto"){
//Properties Services is Google Script Storage.
//This clears out the storage.
PropertiesService.getScriptProperties().deleteAllProperties();
const ss = SpreadsheetApp.getActiveSpreadsheet();
//const sheet = SpreadsheetApp.openById(ssID);
const sheet = ss.getSheetByName("Lista de Participantes");
//Get number of rows to process
rowLen = (rowLen = "auto") ? getRowLen() : rowLen;
const range = sheet.getRange(7,1,rowLen,sheet.getDataRange().getNumColumns());
const matrix = range.getValues();
const fileNameRows = getFileNameRows()
for(let i = 1; i < rowLen; i++){
if (matrix[i][1] == true && matrix[i][27] != "Sim") {
let row = matrix[i];
//Get the title for the file.
let fileName = buildFileName(row)
//Creates a copy of the template file and names it with the current row's details.
let newDoc = DriveApp.getFileById(templateID).makeCopy(fileName);
//Replaces all the text place markers ({{text}}) with current row information.
updateFileData(row, newDoc.getId());
//Save new File ID and email to Properties service.
PropertiesService.getScriptProperties()
.setProperty(newDoc.getId(),row[emailCol]);
// 5. Export the temporal Google Slides as a PDF file.
newDoc = DriveApp.getFileById(newDoc.getId());
DriveApp.getFolderById("folder ID").createFile(newDoc.getBlob());
}
};
Besides the code above, I go this script file within the same container/Spreadsheet, where I map the columns whose data I want to generate a google Slide for. each column of data I refer to as marker.
/*###################################################################
* Maps the relationship between the Google Sheet header and its location
* for each column along with it's corresponding Google Slide Doc template name.
*
* To update change the sheet, col and doc:
* ***
* {
* sheet: << Your sheet header
* col: << The column on the google sheet with the above header
* doc: << the corresonding name in double braces {{name}} in your Slide template
* }
* ***
*###################################################################
*/
const mappedDocToSheet = [
{
sheet:"Nome",
col:2,
doc:"primeiroNome"
},
{
sheet:"Sobrenome",
col:3,
doc:"sobrenome"
},
{
sheet:"COD. CERTIFICADO",
col:9,
doc:"codigo"
},
{
sheet:"Curso",
col:10,
doc:"curso"
},
];
I believe your goal and situation as follows.
You add the values of Google Slides and create it to PDF data
newDoc is the Google Slides
In order to achieve your goal, please use saveAndClose. For your script, please modify as follows.
Modified script:
Please add the following script to your function of mailMerge as follows.
// 5. Export the temporal Google Slides as a PDF file.
SlidesApp.openById(newDoc.getId()).saveAndClose(); // <--- Added
Reference:
saveAndClose()

CMS and store hi-resolution images in generated pdf

I'm looking for good CMS for publishing software manuals.
Requirements:
publish manual pages as web pages with thumbnails and shows full resolution after click on image,
exporting manual pages to a pdf file with full resolution images instead to thumbnails.
I found IMHO best wiki system named Tiki Wiki (https://info.tiki.org/) but when I export to pdf then I gets low resolution thumbnail.
I solve this problem by very simple Tiki Wiki code modification:
Modify lib/wiki-plugins/wikiplugin_img.php to force using full image resolution instead to thumbnail in print page mode (inserted code 1) and rescale images in generated HTML by 0.5 factor (inserted code 2):
[...]
function wikiplugin_img( $data, $params )
{
[...]
$imgdata = array_merge($imgdata, $params);
// inserted code 1 (~410 line)
if ($GLOBALS['section_class']=="tiki_wiki_page print"){
$imgdata['thumb'] = '';
}
// end of inserted code 1
//function calls
if ( !empty($imgdata['default']) || !empty($imgdata['mandatory'])) {
[...]
$fwidth = '';
$fheight = '';
if (isset(TikiLib::lib('parser')->option['indexing']) && TikiLib::lib('parser')->option['indexing']) {
$fwidth = 1;
$fheight = 1;
} else {
// inserted code 2 (~410 line)
if ($GLOBALS['section_class']=="tiki_wiki_page print"){
$fwidth = $imageObj->get_width() / 2;
$fheight = $imageObj->get_height() / 2;
} else {
$fwidth = $imageObj->get_width();
$fheight = $imageObj->get_height();
}
// end of inserted code 2 (~638 line)
}
[...]
Now, after printing to pdf by wkhtmltopdf we gets pdf with small but full resolution images.
Additional modifies:
Adds following lines to cms/cssmenus.css (or other css included in print mode) for increase bottom margin of image caption:
div.thumbcaption {
margin-bottom: 5mm;
}
Removes lines from 171 to ~175 in templates/tiki-show_content.tpl for remove the "The original document is available at" foot.

How to remove blank pages from PDF using PDFSHarp?

How will i be able to remove a blank page from a PDF file? I have a sample PDF file where the 1st page contains a few strings and a 2nd page with absolutely NOTHING in it. I tried to loop into the pdf pages and get the element count PER page but the funny thing is that i get the same number between the 2 pages =| How did that happen if the 1st page has a few strings and the 2nd page was absolutely blank???
This is my code
Dim inputDOcument As PdfDocument = PdfReader.Open("")
Dim elemountCount As Integer = 0
Dim elemountCount2 As Integer = 0
Dim pdfPageCount As Integer = inputDOcument.PageCount
For x As Integer = 0 To pdfPageCount - 1
elemountCount = inputDOcument.Pages(x).Contents.Elements.Count
elemountCount2 = inputDOcument.Pages(x).Elements.Count
Next
Try to check length of each element:
public bool HasContent(PdfPage page)
{
for(var i = 0; i < page.Contents.Elements.Count; i++)
{
if (page.Contents.Elements.GetDictionary(i).Stream.Length > 76)
{
return true;
}
}
return false;
}
You can try the PDFsharp Document Explorer that comes with PDFsharp to see what the PDF file really contains.
Or load and save the file with a PDFsharp DEBUG build, this will give you a "verbose" file. Viewing that with Notepad could help to understand what the file contains.

Content templates rendering in TYPO3

I've got a strange problem connected with content rendering.
I use following code to grab the content:
lib.otherContent = CONTENT
lib.otherContent {
table = tt_content
select {
pidInList = this
orderBy = sorting
where = colPos=0
languageField = sys_language_uid
}
renderObj = COA
renderObj {
10 = TEXT
10.field = header
10.wrap = <h2>|</h2>
20 = TEXT
20.field = bodytext
20.wrap = <div class="article">|</div>
}
}
and everything works fine, except that I'd like to use also predefined column-content templates other than simple text (Text with image, Images only, Bullet list etc.).
The question is: with what I have to replace renderObj = COA and the rest between the brackets to let the TYPO3 display it properly?
Thanks,
I.
The available cObjects are more or less listed in TSRef, chapter 8.
TypoScript for rendering Text w/image can be found in typo3/sysext/css_styled_content/static/v4.3/setup.txt at line 724, and in the neighborhood you'll find e.g. bullets (below) and image (above), which is referenced in textpic line 731. Variants of this is what you'll write in your renderObj.
You will find more details in the file typo3/sysext/cms/tslib/class.tslib_content.php, where e.g. text w/image is found at or around line 897 and is called IMGTEXT (do a case-sensitive search). See also around line 403 in typo3/sysext/css_styled_content/pi1/class.cssstyledcontent_pi1.php, where the newer css-based rendering takes place.