I use abcpdf to create a pdf from a html string. The following snippet shows the way I do it:
var pdfDocument = new Doc();
pdfDocument.Page = pdfDocument.AddPage();
pdfDocument.Font = pdfDocument.AddFont("Times-Roman");
pdfDocument.FontSize = 12;
var documentId = pdfDocument.AddImageHtml(innerHtml);
var counter = 0;
while (true)
{
counter++;
if (!pdfDocument.Chainable(documentId))
{
break;
}
pdfDocument.Page = pdfDocument.AddPage();
// how to add a inset of 20, 0 on every page after the second? The following 2lines don't affect the pdf pages
if (counter >= 3)
pdfDocument.Rect.Inset(20, 0);
documentId = pdfDocument.AddImageToChain(documentId);
}
After the AddPage I want to add a new inset for every page with pagenumber > 2
Thanks in advance
I can assure you that your inset call will be having an effect. Try calling FrameRect on each page and you shuld be able to see this.
So why is it that you are not seeing the effect you are expecting?
Well your HTML has a fixed width at the point you call AddImageUrl/HTML. Each subsequent call to AddImageToChain utilizes this fixed width.
If in your 'inset' pages you reduce the height of the area on the page you will get the next chunk of the page truncated to that height.
If in your 'inset' pages you reduce the width of the area then things become more difficult. The width is fixed so it can't be changed. Instead ABCpdf will scale the page down so that it does fit.
So if you reduce the width from say 600 points to 580 points then the scale factor for this content would be 580/600 = 97%.
Most likely this is what is happening but because the scale factor is small you are not noticing it.
I work on ABCpdf and my replies may contain concepts based around ABCpdf. It's what I know. :-)
Comment #1 from SwissCoder was right. AddImageHtml already adds the first page. After also contacting the WebSuperGoo support, they recommend me to use PageCountof class Doc.
while (true)
{
if (!pdfDocument.Chainable(documentId))
{
break;
}
pdfDocument.Page = pdfDocument.AddPage();
if (pdfDocument.PageCount >= 3)
pdfDocument.Rect.Inset(0, 20);
documentId = pdfDocument.AddImageToChain(documentId);
}
The other solution would be to adjust the index to count unto required pagenumber - 1 as ÀddImageHtml already adds the first page to the document.
Related
I have doc and change page size
builder.PageSetup.PageWidth = ConvertUtil.MillimeterToPoint(219.1);
builder.PageSetup.PageHeight = ConvertUtil.MillimeterToPoint(285.7);
Doc has Table of content, but after changed size it placed wrong
wrong sized TOC
Any suggestions how to place normal TOC full page width?
Tried with different docs. Same problem.
Width of the TOC is defined by tab stops in the TOC styles. So, after increasing width of the page, you have also increase size of the TOC styles tab stops accordingly. Please see the following code:
Document doc = new Document(#"C:\Temp\in.docx");
doc.FirstSection.PageSetup.PageWidth = doc.FirstSection.PageSetup.PageWidth + 200;
UpdateTocStyles(doc);
// Update fields to rebuild the TOC.
doc.UpdateFields();
doc.Save(#"C:\Temp\out.docx");
private void UpdateTocStyles(Document doc)
{
// List of all TOC styles.
StyleIdentifier[] tocStyles = new StyleIdentifier[]
{
StyleIdentifier.Toc1,
StyleIdentifier.Toc2,
StyleIdentifier.Toc3,
StyleIdentifier.Toc4,
StyleIdentifier.Toc5,
StyleIdentifier.Toc6,
StyleIdentifier.Toc7,
StyleIdentifier.Toc8,
StyleIdentifier.Toc9
};
// Calculate width of the page without left and right margins.
double pageWidth = doc.FirstSection.PageSetup.PageWidth - doc.FirstSection.PageSetup.RightMargin - doc.FirstSection.PageSetup.LeftMargin;
// Reset tab stops in TOC styles.
foreach (StyleIdentifier tocStyleIdentifier in tocStyles)
{
Style tocStyle = doc.Styles[tocStyleIdentifier];
tocStyle.ParagraphFormat.TabStops.Clear();
tocStyle.ParagraphFormat.TabStops.Add(new TabStop(pageWidth, TabAlignment.Right, TabLeader.Dots));
}
}
I have two PDF files with different orientations (first document is A4 format and the second A4 landscape).
I want to merge them but I need to preserve the original orientation of each page.
I tried with the rotation with this code:
float width = pdfImportedPage.Width;
float height = pdfImportedPage.Height;
if (width > height)
{
PdfDictionary pageDict = reader.GetPageN(documentPage);
pageDict.Put(PdfName.ROTATE, new PdfNumber(270));
}
After the rotation I call the AddPage method like this:
copy.AddPage(pdfImportedPage);
But the result is an A4 format document with the second part with the text that goes out of the page. For me is good if the text in the second part is horizontal but I need that also the orientation of the page will be as the original document (horizontal).
I'm using iTextSharp version 5.5.13.
I've just discovered that the problem was in another part of the code, after that, when I add the page number.
By the way, a good way to preserve the page orientation is to use the SetPageSize and the NewPage methods, like this piece of code:
for (int page = 1; page <= reader.NumberOfPages; page++)
{
copy.RotateContents = true;
doc.SetPageSize(reader.GetPageSizeWithRotation(page));
doc.NewPage();
importedPage = copy.GetImportedPage(reader, page);
copy.AddPage(importedPage);
}
I have big problem with EPPlus. When I create simple Excel file with 20 images from local resource (disk C:) - everything is OK - it lasts ~3 second. But when I try to do it with >200 pictures - I have to wait ~20 sec to generate file. With 500 items I have to wait ~4 minutes... Why? What I can do to fix that problem?
That's my code:
Image image = Image.FromFile(filePath);
string name = "pic" + rowIndex.ToString() + columnIndex.ToString();
using (ExcelPicture picture = ws.Drawings.AddPicture(name, image))
{
image.Dispose();
picture.From.Column = columnIndex;
picture.To.Column = columnIndex;
picture.From.Row = rowIndex;
picture.To.Row = rowIndex;
picture.From.ColumnOff = Pixel2MTU(3);
picture.From.RowOff = Pixel2MTU(2);
picture.SetSize(width, height);
if (position > 0)
{
picture.SetPosition(0, position);
}
}
I have noticed that while AddPicture has improved speed after the latest update - however setting the row and column offset of the picture is getting progressively slower. And when i analysed the source code it seems for each of this property lot of background work is happening on xml.
I encountered the same problem, I have a solution, that is, I can calculate the size of each picture ,then calculate the row height according to the picture size, and adjust the height of the entire workbook according to their row height calculated from above info. finally add the picture,
in short ,set the desired rows height before you add any picture.
I hope it will be useful to you
Why I am getting border on bottom and right when rendering html using abcAdf.
PS I got professional license using (ABCpdf9-64.dll)
My process is to create page:
I use master / child layout template in mvc (works)
I point to this html using abcPdf to convert into pdf
Html rendered
When my html gets rendered (plain) format : each originating from its respective location.
<h1>Layout</h1>
<p>
content
</p>
C# code to render pdf
My code is as follows:
using (var pdf = new Doc())
{
pdf.HtmlOptions.Timeout = 600000;
pdf.HtmlOptions.AddTags = true;
pdf.Page = pdf.AddPage();
var id = pdf.AddImageUrl(url, true, 1024, true);
if (allowPaging)
{
while (true)
{
if (!pdf.Chainable(id))
{
break;
}
pdf.Page = pdf.AddPage();
id = pdf.AddImageToChain(id);
}
for (int i = 1; i <= pdf.PageCount; i++)
{
pdf.PageNumber = i;
pdf.Flatten();
}
////reset back to page 1 so the pdf starts displaying there
if (pdf.PageCount > 0)
{
pdf.PageNumber = 1;
}
}
return store(pdf);
}
Output
My text/html gets rendered ok but I get borders that I have not asked for.
Rendered output:
Please note the hairline in bottom of the image.
After hours of googling about setting margin in abcpdf, I found nothing and took it as a challenge to find it myself.
I tried experimenting with everything I found relevant in the abcpdf documentation and finally made a chart myself
for setting the margins. I have successfully implemented this in many situations. Hope this helps others.
Here is a code snippet that shows how to set margins-
string html; // my html content that should be shown in the pdf page
Doc pdf = new Doc();
// adjust the default rotation and save
double w = pdf.MediaBox.Width;
double h = pdf.MediaBox.Height;
double l = pdf.MediaBox.Left;
double b = pdf.MediaBox.Bottom;
// explicitly giving page size
pdf.MediaBox.String = "A4";
pdf.Transform.Rotate(90, l, b);
pdf.Transform.Translate(w, 0);
pdf.Rect.Width = h;
pdf.Rect.Height = w;
int theID1 = pdf.GetInfoInt(pdf.Root, "Pages");
pdf.SetInfo(theID1, "/Rotate", "90");
int theID;
pdf.Rect.String = "17 55 823 423";
theID = pdf.AddImageHtml(html.ToString()); //Writes the HTML image to PDF
Here is a picture that describes margin layout for some junk values. Here
20 suggests that your content starts 20 pixels away from left of your pdf page
770 suggests that your content ends 770 pixels away from left of your pdf page
75 suggests that your content starts 55 pixels above the bottom of your pdf page
600 suggests that your content ends 600 pixels above the bottom of your pdf page
In your case you have to add
pdf.Rect.String = "20 75 770 600"; // giving junk values
right before
var id = pdf.AddImageUrl(url, true, 1024, true);
NOTE: In this example I explicitly set landscape mode instead of portrait mode. But orientation doesn't matter for setting
margins.
I currently have a function that is able to printout a DataGridView onto a page using System.Drawing.Printing.PrintDocument - the printing utility runs through my print page function (PrintDoc_PagePrint) until it runs out of rows (where it will set HasMorePages to false.)
I'm trying to work out the total number of pages before I print so I can put "page x of y" at the bottom of each page. One way is to work out how many rows fit on each page and work out how many pages there are based on how many rows there are in total, but this doesn't seem very versatile as it relies on each row being the same height, which depending on how it's programmed, may not always be the case.
The way I want to do it is to do a "phantom" print - or basically print it to a null printer in the background without the user knowing. When it does this first print, it can increment a global variable TotalPages each time it runs the print function, then once the phantom print is done stop TotalPages being incremented next time it is printed (presumably just by setting a bool once the phantom print is done.) This would be more versatile, and would work for data grids with different row heights, or any other type of data I wanted to print.
My question is - is there any way to run a sample print in the background? This is done after the user has selected page size and orientation etc, so we do know those essential details, but just before the print preview dialogue is displayed.
Here's some code I have... it sort of works, but for some reason it doesn't work all the time!
// Phantom print to determine number of pages. Writes to TotalPages var.
// The next print won't write to TotalPages when FirstPreviewDone is set to true.
var printEventArgs = new PrintEventArgs();
// Create a graphics object of the page size to "print" to.
int x = 0;
int y = 0;
int width = printDoc.DefaultPageSettings.PaperSize.Width;
int height = printDoc.DefaultPageSettings.PaperSize.Height;
Rectangle marginBoundsRectangle = new Rectangle(x, y, width, height);
Rectangle pageBoundsRectangle = new Rectangle(0, 0, printDoc.DefaultPageSettings.PaperSize.Width, printDoc.DefaultPageSettings.PaperSize.Height);
Bitmap b = new Bitmap(width, height);
// Swap everything if it's in landscape.
if (printDoc.DefaultPageSettings.Landscape)
{
marginBoundsRectangle = new Rectangle(y, x, height, width);
pageBoundsRectangle = new Rectangle(0, 0, printDoc.DefaultPageSettings.PaperSize.Height, printDoc.DefaultPageSettings.PaperSize.Width);
b = new Bitmap(height, width);
}
Graphics graphics = Graphics.FromImage(b);
var printPageEventArgs = new PrintPageEventArgs(graphics, marginBoundsRectangle, pageBoundsRectangle, printDoc.DefaultPageSettings);
printPageEventArgs.HasMorePages = true;
PrintDoc_BeginPrint(null, printEventArgs);
while (printPageEventArgs.HasMorePages && !printPageEventArgs.Cancel)
{
try
{
PrintDoc_PrintPage(null, printPageEventArgs);
}
catch (Exception ex)
{
MessageBoxEx.Show(ex.Message, "Error printing - Check logs", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
This is already answered in the below question...
Is there a better way to get the page count from a PrintDocument than this?
Hope this helps...
int iPageCount = rptDocument.FormatEngine.GetLastPageNumber(new ReportPageRequestContext());