0

I've read the MigraDoc/PdfSharp documentation, but it feels a bit thin. I want to render out a PDF, but not have to manually specify width and height. I just want it to align right, center, or left (of margins), and handle all the sizing for me.

Public Sub Write()
    Dim document As PdfDocument = New PdfDocument()
    Dim page As PdfPage = document.AddPage()

    Dim gfx As XGraphics = XGraphics.FromPdfPage(page)
    gfx.MUH = PdfFontEncoding.Unicode
    gfx.MFEH = PdfFontEmbedding.Default

    Dim font As XFont = New XFont("Verdana", 13, XFontStyle.Bold)

    Dim migraDocument As New Document

    Dim sec As Section = migraDocument.AddSection()

    Dim quotationHeader As New Paragraph
    quotationHeader.AddText("Quotation" & vbNewLine)
    quotationHeader.Format.Alignment = ParagraphAlignment.Right
    sec.Add(quotationHeader)

    Dim dhAddressInfo As New Paragraph
    dhAddressInfo.AddText("ADDRESS GOES HERE")
    dhAddressInfo.Format.Alignment = ParagraphAlignment.Left
    sec.Add(dhAddressInfo)

    Dim quotationInfo As New Paragraph
    quotationInfo.AddText("QUOTATION INFO AND DATE HERE")
    quotationInfo.Format.Alignment = ParagraphAlignment.Right
    sec.Add(quotationInfo)

    Dim customerBilling As New Paragraph
    With Customer
        customerBilling.AddText("CUSTOMER BILLING OBJECT PROPERTIES HERE")
    End With
    customerBilling.Format.Alignment = ParagraphAlignment.Left
    sec.Add(customerBilling)

    Dim authorInfo As New Paragraph
    authorInfo.AddText("AUTHOR INFO HERE")
    authorInfo.Format.Alignment = ParagraphAlignment.Right
    sec.Add(authorInfo)

    Dim pricingTable As New Table
    'pricingTable.Format.Alignment = ParagraphAlignment.Center

    pricingTable.AddColumn("13cm")
    pricingTable.AddColumn("13cm")

    Dim headerRow As New Row
    headerRow = pricingTable.AddRow()

    headerRow.HeadingFormat = True
    headerRow.Cells(0).AddParagraph("Description")
    headerRow.Cells(1).AddParagraph("Amount")

    For i As Integer = 0 To SelectedPrices.Count - 1
        Dim row As Row = pricingTable.AddRow()
        Dim price As Pricing = SelectedPrices(i)

        row.Cells(0).AddParagraph(price.Item)
        row.Cells(1).AddParagraph(price.Price * price.Quantity)
    Next

    Dim totalRow As Row = pricingTable.AddRow()
    totalRow.Cells(0).AddParagraph("Total: ")
    Dim total As Double = 0

    For Each price As Pricing In SelectedPrices
        total = total + (price.Price * price.Quantity)
    Next

    totalRow.Cells(1).AddParagraph(total.ToString)

    sec.Add(pricingTable)

    Dim docRenderer As DocumentRenderer = New DocumentRenderer(migraDocument)
    docRenderer.PrepareDocument()

    docRenderer.RenderObject(gfx, XUnit.FromCentimeter(0), XUnit.FromCentimeter(0), "10cm", quotationHeader)
    docRenderer.RenderObject(gfx, XUnit.FromCentimeter(0), XUnit.FromCentimeter(2), "10cm", dhAddressInfo)
    docRenderer.RenderObject(gfx, XUnit.FromCentimeter(5), XUnit.FromCentimeter(2), "10cm", quotationInfo)
    docRenderer.RenderObject(gfx, XUnit.FromCentimeter(0), XUnit.FromCentimeter(6), "10cm", customerBilling)
    docRenderer.RenderObject(gfx, XUnit.FromCentimeter(5), XUnit.FromCentimeter(6), "10cm", authorInfo)
    docRenderer.RenderObject(gfx, XUnit.FromCentimeter(3), XUnit.FromCentimeter(10), "10cm", pricingTable)

    document.Save(Environment.CurrentDirectory & "\test.pdf")
End Sub

Notice at the bottom I'm specifying the X and Y coordinates of each section. I just want to define spacing. Alignment should take care of the rest.

user287848
  • 141
  • 1
  • 12
  • If you want automatic PDF rendering, why don't you let MigraDoc create the PDF for you? I think I'd use a MigraDoc table to position the paragraphs - completely without X and Y co-ordinates. – I liked the old Stack Overflow May 19 '16 at 18:11
  • I am. I do reference PdfSharp but I'm not using it. It was left over from a MigraDoc tutorial, and it wasn't too clear how PdfSharp was incorporated. I was also told you needed to use both PdfSharp and MigraDoc because they both needed each other (one could write, one could render). Either way, I found another site that demonstrated it pretty clearly. – user287848 May 19 '16 at 18:23

1 Answers1

0

I found a different tutorial that uses PdfDocumentRenderer and shows how to correctly use it. It's not in VB, but quite easily translated. I copied it below in case the link goes dead.

http://www.c-sharpcorner.com/UploadFile/aftab_ku/create-object-model-document-and-renders-them-into-pdf/

public Document CreateDocument()
{
    // Create a new MigraDoc document
    this.document = new Document();
    this.document.Info.Title = "";
    this.document.Info.Subject = "";
    this.document.Info.Author = "Aftab";

    DefineStyles();
    CreatePage();
    FillContent();
    return this.document;
}

Here, CreateDocument() in PDFform.cs creates a new MigraDoc. Take a look at the three functions called for creating style and page and fill the content of the tables.

//
void DefineStyles()
{
    // Get the predefined style Normal.
    Style style = this.document.Styles["Normal"];

    // Because all styles are derived from Normal, the next line changes the 
    // font of the whole document. Or, more exactly, it changes the font of

    // all styles and paragraphs that do not redefine the font.
    style.Font.Name = "Verdana";

    style = this.document.Styles[StyleNames.Header];
    style.ParagraphFormat.AddTabStop("16cm", TabAlignment.Right); 
    style = this.document.Styles[StyleNames.Footer];
    style.ParagraphFormat.AddTabStop("8cm", TabAlignment.Center); 

    // Create a new style called Table based on style Normal
    style = this.document.Styles.AddStyle("Table", "Normal");
    style.Font.Name = "Verdana";
    style.Font.Name = "Times New Roman";
    style.Font.Size = 9; 

    // Create a new style called Reference based on style Normal
    style = this.document.Styles.AddStyle("Reference", "Normal");
    style.ParagraphFormat.SpaceBefore = "5mm";
    style.ParagraphFormat.SpaceAfter = "5mm";
    style.ParagraphFormat.TabStops.AddTabStop("16cm", TabAlignment.Right);
}

DefineStyles() does the job of styling the document:

void CreatePage()
{
    // Each MigraDoc document needs at least one section.
    Section section = this.document.AddSection(); 
    // Put a logo in the header
    Image image= section.AddImage(path); 
    image.Top = ShapePosition.Top;
    image.Left = ShapePosition.Left;
    image.WrapFormat.Style = WrapStyle.Through;

    // Create footer
    Paragraph paragraph = section.Footers.Primary.AddParagraph();
    paragraph.AddText("Health And Social Services.");
    paragraph.Format.Font.Size = 9;
    paragraph.Format.Alignment = ParagraphAlignment.Center; 
    ............

    // Create the item table
    this.table = section.AddTable();
    this.table.Style = "Table";
    this.table.Borders.Color = TableBorder;
    this.table.Borders.Width = 0.25;
    this.table.Borders.Left.Width = 0.5;
    this.table.Borders.Right.Width = 0.5;
    this.table.Rows.LeftIndent = 0;

    // Before you can add a row, you must define the columns
    Column column;
    foreach (DataColumn col in dt.Columns)
    {
        column = this.table.AddColumn(Unit.FromCentimeter(3));
        column.Format.Alignment = ParagraphAlignment.Center;
    } 
    // Create the header of the table
    Row row = table.AddRow();
    row.HeadingFormat = true;
    row.Format.Alignment = ParagraphAlignment.Center;
    row.Format.Font.Bold = true;
    row.Shading.Color = TableBlue; 
    for (int i = 0; i < dt.Columns.Count; i++)
    {
        row.Cells[i].AddParagraph(dt.Columns[i].ColumnName);
        row.Cells[i].Format.Font.Bold = false;
        row.Cells[i].Format.Alignment = ParagraphAlignment.Left;
        row.Cells[i].VerticalAlignment = VerticalAlignment.Bottom;
    }

    this.table.SetEdge(0, 0, dt.Columns.Count, 1, Edge.Box, 
         BorderStyle.Single, 0.75, Color.Empty);
}

Here CreatePage() adds a header, footer, and different sections into the document and then the table is created to display the records. Columns from the datatable are added into the table inside the document and then a header row that contains the column names is added.

column = this.table.AddColumn(Unit.FromCentimeter(3));
//creates a new column and width of the column is passed as a parameter. 
Row row = table.AddRow();

//A new header row is created   
row.Cells[i].AddParagraph(dt.Columns[i].ColumnName);

//this will add the column name to header of the row. 
this.table.SetEdge(0, 0, dt.Columns.Count, 1, Edge.Box, 
       BorderStyle.Single, 0.75, Color.Empty);
//sets the border of the row

void FillContent()
{
    ............... 
    Row row1;
    for (int i = 0; i < dt.Rows.Count; i++)
    { 
        row1 = this.table.AddRow();
        row1.TopPadding = 1.5;

        for (int j = 0; j < dt.Columns.Count; j++)
        {
            row1.Cells[j].Shading.Color = TableGray;
            row1.Cells[j].VerticalAlignment = VerticalAlignment.Center;

            row1.Cells[j].Format.Alignment = ParagraphAlignment.Left;
            row1.Cells[j].Format.FirstLineIndent = 1;
            row1.Cells[j].AddParagraph(dt.Rows[i][j].ToString());

            this.table.SetEdge(0, this.table.Rows.Count - 2, dt.Columns.Count, 1, 
                 Edge.Box, BorderStyle.Single, 0.75);
        }
    } 
    .............
}   

FillContent() fills the rows from the datatable into the table inside the document:

row1.Cells[j].AddParagraph(dt.Rows[i][j].ToString());
//adds the value of column into the table row

The Default.aspx file contains the code for generating the PDF:

using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using System.Diagnostics;

MigraDoc libraries are used for generating PDF documents, and System.Diagnostics for starting a PDF Viewer:

PDFform pdfForm = new PDFform(GetTable(), Server.MapPath("img2.gif"));

// Create a MigraDoc document
Document document = pdfForm.CreateDocument();
document.UseCmykColor = true;

// Create a renderer for PDF that uses Unicode font encoding
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(true);

// Set the MigraDoc document
pdfRenderer.Document = document; 

// Create the PDF document
pdfRenderer.RenderDocument();

// Save the PDF document...
string filename = "PatientsDetail.pdf"; 
pdfRenderer.Save(filename);

// ...and start a viewer.
Process.Start(filename);

The PdfForm object is created and using it, a new MigraDoc is generated. PdfDocumentRenderer renders the PDF document and then saves it. Process.Start(filename) starts a PDF viewer to open the PDF file created using MigraDoc.

user287848
  • 141
  • 1
  • 12