Beispiel #1
0
        /// <summary>
        /// Implementation to execute when replace action.
        /// </summary>
        /// <param name="input">stream input</param>
        /// <param name="context">Input context</param>
        /// <returns>
        /// <para>
        /// A <see cref="ReplaceResult"/> reference that contains the result of the operation, to check if the operation is correct, the <b>Success</b>
        /// property will be <b>true</b> and the <b>Value</b> property will contain the value; Otherwise, the the <b>Success</b> property
        /// will be false and the <b>Errors</b> property will contain the errors associated with the operation, if they have been filled in.
        /// </para>
        /// <para>
        /// The type of the return value is <see cref="ReplaceResultData"/>, which contains the operation result
        /// </para>
        /// </returns>
        protected override ReplaceResult ReplaceImpl(Stream input, IInput context)
        {
            if (Style == null)
            {
                Style = PdfTableStyle.Default;
            }

            return(ReplaceImpl(context, input, Text, ReplaceOptions, Table, FixedWidth, TableOffset, Style, UseTestMode));
        }
        private void button1_Click(object sender, EventArgs e)
        {
            String[] data
                =
                {
                "Name;Capital;Continent;Area;Population",
                "Argentina;Buenos Aires;South America;2777815;32300003",
                "Bolivia;La Paz;South America;1098575;7300000",
                "Brazil;Brasilia;South America;8511196;150400000",
                "Canada;Ottawa;North America;9976147;26500000",
                "Chile;Santiago;South America;756943;13200000",
                "Colombia;Bagota;South America;1138907;33000000",
                "Cuba;Havana;North America;114524;10600000",
                "Ecuador;Quito;South America;455502;10600000",
                "El Salvador;San Salvador;North America;20865;5300000",
                "Guyana;Georgetown;South America;214969;800000",
                "Jamaica;Kingston;North America;11424;2500000",
                "Mexico;Mexico City;North America;1967180;88600000",
                "Nicaragua;Managua;North America;139000;3900000",
                "Paraguay;Asuncion;South America;406576;4660000",
                "Peru;Lima;South America;1285215;21600000",
                "United States of America;Washington;North America;9363130;249200000",
                "Uruguay;Montevideo;South America;176140;3002000",
                "Venezuela;Caracas;South America;912047;19700000"
                };

            String[][] dataSource
                = new String[data.Length][];
            for (int i = 0; i < data.Length; i++)
            {
                dataSource[i] = data[i].Split(';');
            }

            //Create a pdf document
            PdfDocument doc = new PdfDocument();

            doc.LoadFromFile(@"..\..\..\..\..\..\Data\TableBorder.pdf");

            PdfPageBase page = doc.Pages[0];

            //Create a pdf table
            PdfTable table = new PdfTable();

            //Set data source of the pdf table
            table.DataSource = dataSource;

            //Set the color of table border
            PdfTableStyle style = new PdfTableStyle();

            style.CellPadding = 2;
            style.BorderPen   = new PdfPen(Color.Gray, 1f);
            table.Style       = style;

            //Add custom method to BeginRowLayout event
            table.BeginRowLayout += new BeginRowLayoutEventHandler(table_BeginRowLayout);

            //Draw the pdf table into pdf document
            table.Draw(page, new PointF(60, 320));

            string output = "TableBorder.pdf";

            //Save pdf document
            doc.SaveToFile(output);

            //Launch the Pdf file
            PDFDocumentViewer(output);
        }
        ////////////////////////////////////////////////////////////////////
        // Create charting examples PDF document
        ////////////////////////////////////////////////////////////////////

        public void CreateStockTable()
        {
            const Int32 ColDate   = 0;
            const Int32 ColOpen   = 1;
            const Int32 ColHigh   = 2;
            const Int32 ColLow    = 3;
            const Int32 ColClose  = 4;
            const Int32 ColVolume = 5;

            // Add new page
            Page = new PdfPage(Document);

            // Add contents to page
            Contents = new PdfContents(Page);

            // create stock table
            PdfTable StockTable = new PdfTable(Page, Contents, NormalFont, 9.0);

            // divide columns width in proportion to following values
            StockTable.SetColumnWidth(1.2, 1.0, 1.0, 1.0, 1.0, 1.2);

            // set all borders
            StockTable.Borders.SetAllBorders(0.012, Color.DarkGray, 0.0025, Color.DarkGray);

            // make some changes to default header style
            StockTable.DefaultHeaderStyle.Alignment = ContentAlignment.BottomRight;

            // create private style for header first column
            StockTable.Header[ColDate].Style           = StockTable.HeaderStyle;
            StockTable.Header[ColDate].Style.Alignment = ContentAlignment.MiddleLeft;

            StockTable.Header[ColDate].Value   = "Date";
            StockTable.Header[ColOpen].Value   = "Open";
            StockTable.Header[ColHigh].Value   = "High";
            StockTable.Header[ColLow].Value    = "Low";
            StockTable.Header[ColClose].Value  = "Close";
            StockTable.Header[ColVolume].Value = "Volume";

            // make some changes to default cell style
            StockTable.DefaultCellStyle.Alignment = ContentAlignment.MiddleRight;
            StockTable.DefaultCellStyle.Format    = "#,##0.00";

            // create private style for date column
            StockTable.Cell[ColDate].Style           = StockTable.CellStyle;
            StockTable.Cell[ColDate].Style.Alignment = ContentAlignment.MiddleLeft;
            StockTable.Cell[ColDate].Style.Format    = null;

            // create private styles for volumn column
            PdfTableStyle GoingUpStyle = StockTable.CellStyle;

            GoingUpStyle.BackgroundColor = Color.LightGreen;
            GoingUpStyle.Format          = "#,##0";
            PdfTableStyle GoingDownStyle = StockTable.CellStyle;

            GoingDownStyle.BackgroundColor = Color.LightPink;
            GoingDownStyle.Format          = "#,##0";

            // open stock daily price
            // takem from Yahoo Financial
            StreamReader Reader = new StreamReader("SP500.csv");

            // ignore header
            Reader.ReadLine();

            // read all daily prices
            for (;;)
            {
                String TextLine = Reader.ReadLine();
                if (TextLine == null)
                {
                    break;
                }

                String[] Fld = TextLine.Split(new Char[] { ',' });

                StockTable.Cell[ColDate].Value   = Fld[ColDate];
                StockTable.Cell[ColOpen].Value   = Double.Parse(Fld[ColOpen], NFI.PeriodDecSep);
                StockTable.Cell[ColHigh].Value   = Double.Parse(Fld[ColHigh], NFI.PeriodDecSep);
                StockTable.Cell[ColLow].Value    = Double.Parse(Fld[ColLow], NFI.PeriodDecSep);
                StockTable.Cell[ColClose].Value  = Double.Parse(Fld[ColClose], NFI.PeriodDecSep);
                StockTable.Cell[ColVolume].Value = Int32.Parse(Fld[ColVolume]);
                StockTable.Cell[ColVolume].Style = (Double)StockTable.Cell[ColClose].Value >= (Double)StockTable.Cell[ColOpen].Value ? GoingUpStyle : GoingDownStyle;
                StockTable.DrawRow();
            }

            StockTable.Close();

            // exit
            return;
        }
Beispiel #4
0
        // Generates document
        public static void Generate(ILogger logger)
        {
            #region image style

            logger.Info("   > Working with image styles");

            var imageStyle = new PdfImageStyle
            {
                Name    = "ImageStyle",
                Borders =
                {
                    new BaseBorder {
                        Color = "Red", Show = YesNo.Yes, Position = KnownBorderPosition.Right
                    },
                    new BaseBorder {
                        Color = "Yellow", Show = YesNo.Yes, Position = KnownBorderPosition.Top
                    }
                },
                Content =
                {
                    Color     = "Blue",
                    Alignment =
                    {
                        Horizontal = KnownHorizontalAlignment.Right
                    },
                    Properties     = new Properties
                    {
                        new Property {
                            Name   = "p001",Value  = "v001"
                        },
                        new Property {
                            Name   = "p002",Value  = "v002"
                        }
                    }
                }
            };

            // Save image style to disk
            var imageStyleAsXmlResult = imageStyle.SaveToFile("~/Output/Sample12/ImageStyle");
            if (!imageStyleAsXmlResult.Success)
            {
                logger.Info("     > Error while saving image style as xml to disk");
                logger.Info($"      > Error: {imageStyleAsXmlResult.Errors.AsMessages().ToStringBuilder()}");
            }
            else
            {
                logger.Info("     > Saved image style as xml to disk correctly");
                logger.Info("       > Path: ~/Output/Sample12/ImageStyle.xml");
            }

            var imageStyleAsJsonResult = imageStyle.SaveToFile("~/Output/Sample12/ImageStyle", KnownFileFormat.Json);
            if (!imageStyleAsJsonResult.Success)
            {
                logger.Info("     > Error while saving image style as json to disk");
                logger.Info($"      > Error: {imageStyleAsJsonResult.Errors.AsMessages().ToStringBuilder()}");
            }
            else
            {
                logger.Info("     > Saved image style as json to disk correctly");
                logger.Info("       > Path: ~/Output/Sample12/ImageStyle.json");
            }

            // New image style instances from disk
            var imageStyleFromXml = PdfImageStyle.LoadFromFile("~/Output/Sample12/ImageStyle.xml");
            logger.Info(imageStyleFromXml == null
                ? "     > Error while loading image style from xml file"
                : "     > Image style loaded correctly from xml '~/Output/Sample12/ImageStyle.xml' file");

            var imageStyleFromJson = PdfImageStyle.LoadFromFile("~/Output/Sample12/ImageStyle.json", KnownFileFormat.Json);
            logger.Info(imageStyleFromJson == null
                ? "     > Error while loading image style from json file"
                : "     > Image style loaded correctly from json '~/Output/Sample12/ImageStyle.json' file");

            #endregion

            #region text style

            logger.Info("");
            logger.Info("   > Working with text styles");

            var textStyle = new PdfTextStyle
            {
                Name = "NormalStyle",
                Font =
                {
                    Bold      = YesNo.Yes,
                    Italic    = YesNo.Yes,
                    Color     = "Yellow",
                    Underline = YesNo.No
                },
                Borders =
                {
                    new BaseBorder {
                        Color = "Red", Show = YesNo.Yes, Position = KnownBorderPosition.Right
                    },
                    new BaseBorder {
                        Color = "Yellow", Show = YesNo.Yes, Position = KnownBorderPosition.Top
                    }
                },
                Content =
                {
                    Color     = "Blue",
                    Alignment =
                    {
                        Vertical   = KnownVerticalAlignment.Top,
                        Horizontal = KnownHorizontalAlignment.Right
                    },
                    Properties     = new Properties
                    {
                        new Property {
                            Name   = "p001",                    Value  = "v001"
                        },
                        new Property {
                            Name   = "p002",                    Value  = "v002"
                        }
                    }
                }
            };

            // Save text style to disk
            var textStyleAsXmlResult = textStyle.SaveToFile("~/Output/Sample12/TextStyle");
            if (!textStyleAsXmlResult.Success)
            {
                logger.Info("     > Error while saving text style as xml to disk");
                logger.Info($"      > Error: {textStyleAsXmlResult.Errors.AsMessages().ToStringBuilder()}");
            }
            else
            {
                logger.Info("     > Saved text style as xml to disk correctly");
                logger.Info("       > Path: ~/Output/Sample12/TextStyle.xml");
            }

            var textStyleAsJsonResult = textStyle.SaveToFile("~/Output/Sample12/TextStyle", KnownFileFormat.Json);
            if (!textStyleAsJsonResult.Success)
            {
                logger.Info("     > Error while saving text style as json to disk");
                logger.Info($"      > Error: {textStyleAsJsonResult.Errors.AsMessages().ToStringBuilder()}");
            }
            else
            {
                logger.Info("     > Saved text style as json to disk correctly");
                logger.Info("       > Path: ~/Output/Sample12/TextStyle.json");
            }

            // New text style instances from disk
            var textStyleFromXml = PdfTextStyle.LoadFromFile("~/Output/Sample12/TextStyle.xml");
            logger.Info(textStyleFromXml == null
                ? "     > Error while loading text style from xml file"
                : "     > Text style loaded correctly from xml '~/Output/Sample12/TextStyle.xml' file");

            var textStyleFromJson = PdfTextStyle.LoadFromFile("~/Output/Sample12/TextStyle.json", KnownFileFormat.Json);
            logger.Info(textStyleFromJson == null
                ? "     > Error while loading text style from json file"
                : "     > Text style loaded correctly from json '~/Output/Sample12/TextStyle.json' file");

            #endregion

            #region table style

            logger.Info("");
            logger.Info("   > Working with table styles");

            var tableStyle = new PdfTableStyle
            {
                Name      = "NormalStyle",
                Alignment =
                {
                    Vertical = KnownVerticalAlignment.Top
                },
                Borders =
                {
                    new BaseBorder {
                        Color = "Red", Show = YesNo.Yes, Position = KnownBorderPosition.Right
                    },
                    new BaseBorder {
                        Color = "Yellow", Show = YesNo.Yes, Position = KnownBorderPosition.Top
                    }
                },
                Content =
                {
                    Color      = "Blue",
                    Show       = YesNo.Yes,
                    Properties = new Properties
                    {
                        new Property {
                            Name = "p001",   Value  = "v001"
                        },
                        new Property {
                            Name = "p002",   Value  = "v002"
                        }
                    }
                }
            };

            // Save table style to disk
            var tableStyleAsXmlResult = tableStyle.SaveToFile("~/Output/Sample12/TableStyle");
            if (!tableStyleAsXmlResult.Success)
            {
                logger.Info("     > Error while saving table style as xml to disk");
                logger.Info($"      > Error: {tableStyleAsXmlResult.Errors.AsMessages().ToStringBuilder()}");
            }
            else
            {
                logger.Info("     > Saved table style as xml to disk correctly");
                logger.Info("       > Path: ~/Output/Sample12/TableStyle.xml");
            }

            var tableStyleAsJsonResult = tableStyle.SaveToFile("~/Output/Sample12/TableStyle", KnownFileFormat.Json);
            if (!tableStyleAsJsonResult.Success)
            {
                logger.Info("     > Error while saving table style as json to disk");
                logger.Info($"      > Error: {tableStyleAsJsonResult.Errors.AsMessages().ToStringBuilder()}");
            }
            else
            {
                logger.Info("     > Saved table style as json to disk correctly");
                logger.Info("       > Path: ~/Output/Sample12/TableStyle.json");
            }

            // New table style instances from disk
            var tableStyleFromXml = PdfTableStyle.LoadFromFile("~/Output/Sample12/TableStyle.xml");
            logger.Info(tableStyleFromXml == null
                ? "     > Error while loading table style from xml file"
                : "     > Table style loaded correctly from xml '~/Output/Sample12/TableStyle.xml' file");

            var tableStyleFromJson = PdfTableStyle.LoadFromFile("~/Output/Sample12/TableStyle.json", KnownFileFormat.Json);
            logger.Info(tableStyleFromJson == null
                ? "     > Error while loading table style from json file"
                : "     > Table style loaded correctly from json '~/Output/Sample12/TableStyle.json' file");

            #endregion
        }
Beispiel #5
0
        private static ReplaceResult ReplaceImpl(IInput context, Stream input, string oldText, ReplaceTextOptions options, PdfTable table, float fixedWidth, PointF tableOffset, PdfTableStyle style, YesNo useTestMode)
        {
            var outputStream = new MemoryStream();

            try
            {
                using (var reader = new PdfReader(input))
                    using (var stamper = new PdfStamper(reader, outputStream))
                    {
                        var pages = reader.NumberOfPages;
                        for (var page = 1; page <= pages; page++)
                        {
                            var strategy = new CustomLocationTextExtractionStrategy();
                            var cb       = stamper.GetOverContent(page);

                            // Send some data contained in PdfContentByte, looks like the first is always cero for me and the second 100,
                            // but i'm not sure if this could change in some cases.
                            strategy.UndercontentCharacterSpacing  = cb.CharacterSpacing;
                            strategy.UndercontentHorizontalScaling = cb.HorizontalScaling;

                            // It's not really needed to get the text back, but we have to call this line ALWAYS,
                            // because it triggers the process that will get all chunks from PDF into our strategy Object
                            var allStrings   = PdfTextExtractor.GetTextFromPage(reader, page, strategy);
                            var stringsArray = allStrings.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                            // The real getter process starts in the following line
                            var textMatchesFound = strategy.GetExtendedTextLocations(oldText, options).ToList();

                            // MatchesFound contains all text with locations
                            foreach (var match in textMatchesFound)
                            {
                                // Delete tag
                                var bColor = BaseColor.WHITE;
                                cb.SetColorFill(bColor);
                                cb.Rectangle(match.Rect.Left, match.Rect.Bottom, match.Rect.Width, match.Rect.Height);
                                cb.Fill();

                                // Calculates new rectangle
                                var deltaY     = CalculatesVerticalDelta(options, match.Rect);
                                var cellHeight = CalculatesCellHeight(match, oldText, strategy, cb, (string[])stringsArray.Clone(), options, deltaY);
                                var r          = BuildRectangleByStrategies(match, oldText, strategy, cb, (string[])stringsArray.Clone(), options);

                                // Width strategy to use
                                var safeFixedWidth = fixedWidth;
                                var useFixedWidth  = !fixedWidth.Equals(DefaultFixedWidth);
                                if (useFixedWidth)
                                {
                                    if (fixedWidth > r.Width)
                                    {
                                        safeFixedWidth = r.Width;
                                    }
                                }
                                else
                                {
                                    safeFixedWidth = r.Width;
                                }

                                // Creates aligned table by horizontal alignment value (this table contains the user table parameter)
                                var outerBorderTable = new PdfPTable(1)
                                {
                                    TotalWidth          = safeFixedWidth,
                                    HorizontalAlignment = Element.ALIGN_LEFT
                                };

                                var outerCell = PdfHelper.CreateEmptyWithBorderCell(style.Borders);
                                outerCell.MinimumHeight     = cellHeight;
                                outerCell.VerticalAlignment = style.Alignment.Vertical.ToVerticalTableAlignment();
                                outerCell.BackgroundColor   = new BaseColor(ColorHelper.GetColorFromString(style.Content.Color));

                                //table.Table.HorizontalAlignment = Element.ALIGN_LEFT;
                                table.Table.TotalWidth  = safeFixedWidth - (outerCell.EffectivePaddingRight + outerCell.EffectivePaddingLeft) * 2;
                                table.Table.LockedWidth = true; // options.StartStrategy.Equals(StartLocationStrategy.LeftMargin) && options.EndStrategy.Equals(EndLocationStrategy.RightMargin);
                                outerCell.AddElement(table.Table);
                                outerBorderTable.AddCell(outerCell);

                                // Creates strategy table (for shows testmode rectangle)
                                var useTestModeTable = new PdfPTable(1)
                                {
                                    TotalWidth = safeFixedWidth
                                };
                                var useTestCell = PdfHelper.CreateEmptyCell(useTestMode);

                                if (table.Configuration.HeightStrategy == TableHeightStrategy.Exact)
                                {
                                    useTestCell.FixedHeight = table.Table.TotalHeight;
                                }

                                useTestCell.AddElement(outerBorderTable);
                                useTestModeTable.AddCell(useTestCell);
                                useTestModeTable.WriteSelectedRows(-1, -1, r.X + tableOffset.X, r.Y - tableOffset.Y - deltaY, cb);

                                cb.Fill();
                            }

                            cb.Stroke();
                        }

                        stamper.Close();
                        reader.Close();
                    }

                return(ReplaceResult.CreateSuccessResult(new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = new MemoryStream(outputStream.GetBuffer())
                }));
            }
            catch (Exception ex)
            {
                return(ReplaceResult.FromException(
                           ex,
                           new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = input
                }));
            }
        }
        private static void DrawPage(PdfPageBase page, CFDIXML cfdi)
        {
            float pageWidth      = page.Canvas.ClientSize.Width;
            float y              = 0;
            float leftMargin     = 5;
            float midPage        = pageWidth / 2;
            float topWritingArea = 0;
            int   sectionSpacing = 15;
            float qrSize         = 100;

            //Fonts
            string          fontName    = "Arial Condensed";
            PdfTrueTypeFont font7Bold   = new PdfTrueTypeFont(new Font(fontName, 7f, System.Drawing.FontStyle.Bold));
            PdfTrueTypeFont font7       = new PdfTrueTypeFont(new Font(fontName, 7f, System.Drawing.FontStyle.Regular));
            PdfTrueTypeFont font6Italic = new PdfTrueTypeFont(new Font(fontName, 6f, System.Drawing.FontStyle.Italic));

            //Colors
            PdfRGBColor lightBlack = new PdfRGBColor(17, 17, 17);

            //Pen
            PdfPen penLightGray1p   = new PdfPen(System.Drawing.Color.LightGray, 1f);
            PdfPen penLightGray05p  = new PdfPen(System.Drawing.Color.LightGray, 0.5f);
            PdfPen penLightBlack10p = new PdfPen(lightBlack, 10f);

            //Brushes
            PdfBrush brushBlack     = new PdfSolidBrush(System.Drawing.Color.Black);
            PdfBrush brushLightGray = new PdfSolidBrush(System.Drawing.Color.LightGray);

            //Format Alignments
            PdfStringFormat formatRight  = new PdfStringFormat(PdfTextAlignment.Right);
            PdfStringFormat formatMiddle = new PdfStringFormat(PdfTextAlignment.Center, PdfVerticalAlignment.Middle);
            PdfStringFormat formatLeft   = new PdfStringFormat(PdfTextAlignment.Left)
            {
                CharacterSpacing = 0.4f
            };

            //Page header
            String text = "Factura version " + cfdi.Version;

            page.Canvas.DrawString(text, font6Italic, brushLightGray, pageWidth, y, formatRight);
            SizeF size = font6Italic.MeasureString(text, formatRight);

            y = y + size.Height + 1;
            page.Canvas.DrawLine(penLightGray1p, 0, y, pageWidth, y);

            y = y + 5;
            topWritingArea = y;

            //Issuerinfo
            //Name
            DrawToPage(page, cfdi.Emisor.Nombre, font7Bold, brushBlack, formatLeft, leftMargin, y, out y);
            //RFC
            DrawToPage(page, cfdi.Emisor.Rfc, font7Bold, brushBlack, formatLeft, leftMargin, y, out y);
            //Fiscal Regime
            DrawToPage(page, cfdi.Emisor.RegimenFiscal, font7, brushBlack, formatLeft, leftMargin, y, out y);
            //Address
            text = "Calle:" + cfdi.Emisor.Domicilio.Calle + " No:" + cfdi.Emisor.Domicilio.NoExterior;
            if (cfdi.Emisor.Domicilio.NoInterior != null)
            {
                text += "-" + cfdi.Emisor.Domicilio.NoInterior;
            }
            text += " Col:" + cfdi.Emisor.Domicilio.Colonia + ", Localidad:" + cfdi.Emisor.Domicilio.Localidad + ", Municipio:" + cfdi.Emisor.Domicilio.Municipio + ", Estado:" + cfdi.Emisor.Domicilio.Estado + ", CP:" + cfdi.Emisor.Domicilio.Cp;
            RectangleF area = new RectangleF(leftMargin, y, midPage - 10, 30);

            DrawToPage(page, text, font7, brushBlack, formatLeft, area, y, out y, false);
            DrawToPage(page, "Pais:" + cfdi.Emisor.Domicilio.Pais, font7, brushBlack, formatLeft, leftMargin, y, out y);

            //Invoice data
            y = topWritingArea;
            //Invoice header
            y += 5;
            page.Canvas.DrawLine(penLightBlack10p, midPage, y, pageWidth, y);
            text = "Factura";
            size = font7Bold.MeasureString(text, formatLeft);
            y   -= 4;
            DrawToPage(page, text, font7Bold, brushLightGray, formatLeft, pageWidth - size.Width - 10, y, out y);
            //Invoice number
            DrawToPageWithHeader(page, "Folio:", cfdi.Folio, font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);
            DrawToPageWithHeader(page, "Serie:", cfdi.Serie ?? "", font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);
            DrawToPageWithHeader(page, "Folio Fiscal:", cfdi.TimbreFiscal.UUID, font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);
            DrawToPageWithHeader(page, "Serie CSD del SAT:", cfdi.TimbreFiscal.NoCertificadoSAT, font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);
            DrawToPageWithHeader(page, "No. Certificado:", cfdi.NoCertificado, font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);
            DrawToPageWithHeader(page, "Fecha emsión:", cfdi.Fecha, font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);
            DrawToPageWithHeader(page, "Fecha certificación:", cfdi.TimbreFiscal.FechaTimbrado, font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);

            //Issue place
            y += 5;
            DrawToPageWithHeader(page, "Lugar de expedición:", cfdi.LugarExpedicion, font7Bold, font7, brushBlack, formatLeft, leftMargin, y, out y);

            //Reciever data
            //Reciever header
            y += sectionSpacing;
            page.Canvas.DrawLine(penLightBlack10p, leftMargin, y, pageWidth, y);
            text = "Receptor";
            size = font7Bold.MeasureString(text, formatLeft);
            y   -= 4;
            DrawToPage(page, text, font7Bold, brushLightGray, formatLeft, midPage - (size.Width / 2), y, out y);
            //Reciever name
            DrawToPageWithHeader(page, "Receptor:  ", cfdi.Receptor.Nombre, font7Bold, font7, brushBlack, formatLeft, leftMargin, y, out y, true);
            //Reciever address
            text = "Calle:  " + cfdi.Receptor.Domicilio.Calle + " No:" + cfdi.Receptor.Domicilio.NoExterior;
            if (cfdi.Receptor.Domicilio.NoInterior != null)
            {
                text += "-" + cfdi.Receptor.Domicilio.NoInterior;
            }
            DrawToPageWithHeader(page, "Domicilio:   ", text, font7Bold, font7, brushBlack, formatLeft, midPage, y, out y);
            //RFC
            DrawToPageWithHeader(page, "R.F.C.:", cfdi.Receptor.Rfc, font7Bold, font7, brushBlack, formatLeft, leftMargin, y, out y, true);
            //Next line address
            text = " Col:" + cfdi.Receptor.Domicilio.Colonia + ", Localidad:" + cfdi.Receptor.Domicilio.Localidad + ", Municipio:" + cfdi.Receptor.Domicilio.Municipio;
            area = new RectangleF(midPage, y, midPage - 10, 20);
            DrawToPage(page, text, font7, brushBlack, formatLeft, area, y, out y, false);
            text = " Estado:" + cfdi.Receptor.Domicilio.Estado + ", CP:" + cfdi.Receptor.Domicilio.Cp;
            DrawToPage(page, text, font7, brushBlack, formatLeft, midPage, y, out y);
            DrawToPage(page, "Pais:" + cfdi.Receptor.Domicilio.Pais, font7, brushBlack, formatLeft, midPage, y, out y);

            //Products
            y += sectionSpacing;

            //Prepare data
            String[][] dataSource = new String[cfdi.Conceptos.Count + 1][];
            String     headers    = "Cant.;Unidad;Clave;Descripción;Valor unitario;Importe";
            int        i          = 0;

            dataSource[i] = headers.Split(';');
            foreach (Concepto product in cfdi.Conceptos)
            {
                i++;
                String[] content = new String[6];
                content[0]    = product.Cantidad.ToString();
                content[1]    = product.Unidad;
                content[2]    = product.NoIdentificacion;
                content[3]    = product.Descripcion;
                content[4]    = String.Format("{0:N1}", product.ValorUnitario);
                content[5]    = String.Format("{0:C2}", product.Importe);
                dataSource[i] = content;
            }

            //Generate table
            PdfTable      productsTable = new PdfTable();
            PdfTableStyle style         = new PdfTableStyle()
            {
                BorderPen      = new PdfPen(lightBlack, 0.5f),
                CellPadding    = 2,
                HeaderSource   = PdfHeaderSource.Rows,
                HeaderRowCount = 1,
                ShowHeader     = true,
                HeaderStyle    = new PdfCellStyle()
                {
                    BackgroundBrush = new PdfSolidBrush(System.Drawing.Color.Black),
                    TextBrush       = brushLightGray,
                    StringFormat    = formatMiddle
                }
            };

            productsTable.Style = style;

            productsTable.DataSource       = dataSource;
            productsTable.Columns[0].Width = 8;
            productsTable.Columns[3].Width = 30;
            foreach (PdfColumn column in productsTable.Columns)
            {
                column.StringFormat = formatLeft;
            }

            PdfLayoutResult result = productsTable.Draw(page, new PointF(leftMargin, y));

            y = y + result.Bounds.Height + 5;

            //Total in letter and number
            page.Canvas.DrawLine(penLightBlack10p, leftMargin, y, pageWidth, y);
            text = "Total con Letra";
            size = font7Bold.MeasureString(text, formatLeft);
            y   -= 4;
            DrawToPage(page, text, font7Bold, brushLightGray, formatLeft, leftMargin, y, out y);
            DrawToPage(page, Conv.Enletras(cfdi.Total.ToString()) + "M.N.", font7, brushBlack, formatLeft, leftMargin, y, out y, true);

            DrawToPageWithHeader(page, "Subtotal:", String.Format("       {0:C2}", cfdi.SubTotal), font7Bold, font7, brushBlack, formatLeft, midPage + (midPage / 2), y, out y);
            DrawToPageWithHeader(page, "Total:", String.Format("            {0:C2}", cfdi.Total), font7Bold, font7, brushBlack, formatLeft, midPage + (midPage / 2), y, out y);

            //QR Code with basic data
            QRCodeGenerator qrGenerator = new QRCodeGenerator();
            QRCodeData      qrCodeData  = qrGenerator.CreateQrCode(String.Format("?re={0}&rr={1}&tt={2:N1}&id={3}", cfdi.Emisor.Rfc, cfdi.Receptor.Rfc, cfdi.Total, cfdi.TimbreFiscal.UUID), QRCodeGenerator.ECCLevel.Q);
            QRCode          qrCode      = new QRCode(qrCodeData);
            Bitmap          qrCodeImage = qrCode.GetGraphic(20);

            float qrPosition = y;

            PdfImage image = PdfImage.FromImage(qrCodeImage);

            page.Canvas.DrawImage(image, leftMargin, y, qrSize, qrSize);

            //Payment info
            y = qrPosition + sectionSpacing;
            DrawToPageWithHeader(page, "Método de pago:  ", cfdi.MetodoDePago, font7Bold, font7, brushBlack, formatLeft, leftMargin + qrSize, y, out y);
            DrawToPageWithHeader(page, "Cuenta:  ", cfdi.NumCtaPago ?? "", font7Bold, font7, brushBlack, formatLeft, leftMargin + qrSize, y, out y);
            DrawToPageWithHeader(page, "Forma de pago:  ", cfdi.FormaDePago, font7Bold, font7, brushBlack, formatLeft, leftMargin + qrSize, y, out y);
            DrawToPageWithHeader(page, "Condiciones de pago:  ", cfdi.CondicionesDePago ?? "", font7Bold, font7, brushBlack, formatLeft, leftMargin + qrSize, y, out y);

            y = qrPosition + qrSize + sectionSpacing;
            page.Canvas.DrawLine(penLightBlack10p, leftMargin, y, pageWidth, y);
            text = "Cadena original del complemento de certificación del SAT";
            size = font7Bold.MeasureString(text, formatLeft);
            y   -= 4;
            DrawToPage(page, text, font7Bold, brushLightGray, formatLeft, leftMargin, y, out y);
            area = new RectangleF(leftMargin, y, pageWidth - 5, 100);
            DrawToPage(page, String.Format("||{0}|{1}|{2}|{3}|{4}", cfdi.TimbreFiscal.Version, cfdi.TimbreFiscal.UUID, cfdi.TimbreFiscal.FechaTimbrado, cfdi.Sello, cfdi.TimbreFiscal.NoCertificadoSAT), font7Bold, brushBlack, formatLeft, area, y, out y, false);

            y += sectionSpacing;
            page.Canvas.DrawLine(penLightBlack10p, leftMargin, y, pageWidth, y);
            text = "Sello digital del SAT";
            size = font7Bold.MeasureString(text, formatLeft);
            y   -= 4;
            DrawToPage(page, text, font7Bold, brushLightGray, formatLeft, leftMargin, y, out y);
            area = new RectangleF(leftMargin, y, pageWidth - 5, 100);
            DrawToPage(page, cfdi.TimbreFiscal.SelloSAT, font7Bold, brushBlack, formatLeft, area, y, out y, false);

            y += sectionSpacing;
            page.Canvas.DrawLine(penLightBlack10p, leftMargin, y, pageWidth, y);
            text = "Sello digital del contribuyente que lo expide";
            size = font7Bold.MeasureString(text, formatLeft);
            y   -= 4;
            DrawToPage(page, text, font7Bold, brushLightGray, formatLeft, leftMargin, y, out y);
            area = new RectangleF(leftMargin, y, pageWidth - 5, 100);
            DrawToPage(page, cfdi.Sello, font7Bold, brushBlack, formatLeft, area, y, out y, false);

            //Footer
            DrawToPage(page, "Este documento es una representación impresa de un CFDI", font7, brushBlack, formatLeft, midPage, page.Canvas.ClientSize.Height - 30, out y, false);
        }