PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Thu Mar 28, 2024 7:28 pm

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Fri Sep 27, 2019 11:09 am 
Offline

Joined: Tue Aug 06, 2019 10:45 am
Posts: 45
I have a table that I have to know when and if it splits, so that I can add a textframe with the sum value of a columns cell, something like the image attached.

I just need to know how to a split table.

Heres te code that I use to make a quick table:

Code:
        private static Document GenerateTable(int colsCount = 5, int rowsCount = 20)
        {
            #region Valores de costumização da tabela
            // Dimenções da página
            Unit width, height;
            PdfHelper.GetPageSize(PageFormat.A4, out width, out height);

            // Padding da tabela
            Unit tblPadding = 1;

            // Borders das celulas
            Borders cellBorders = new Borders();
            cellBorders.Left.Width = cellBorders.Right.Width = cellBorders.Top.Width = cellBorders.Bottom.Width = 0.5f;
            #endregion Valores de costumização da tabela

            // Criação de objetos primários
            Document doc = new Document();
            var sec = doc.LastSection;
            var tbl = sec.AddTable();
           
            #region Criação de colunas
            Column col = null;
            for(int i = 0; i < colsCount; ++i)
            {
                col = tbl.AddColumn();
                if (i == (colsCount - 1))
                    col.Tag = "Valor";
            }
            #endregion Criação de colunas

            // Largura das colunas.
            tbl.Columns.Width = ((width - 60) / colsCount);

            #region Criação das linhas
            MigraDoc.DocumentObjectModel.Paragraph para = null;
            Row row = null;

            #region Criação dos headers da tabela
            row = tbl.AddRow();
            for(int i = 0; i < colsCount; ++i)
            {
                row[i].Borders = cellBorders.Clone();
                para = row[i].AddParagraph("Coluna: " + i);
                para.Format.Alignment = ParagraphAlignment.Center;
            }

            row.Shading.Color = new MigraDoc.DocumentObjectModel.Color(100, 135, 195, 230);
            row.HeadingFormat = true; // Dizer que esta linha que foi criada é do cabeçalho
            #endregion Criação dos headers da tabela

            #region Criação do body da tabela
            for (int i = 0; i < rowsCount; ++i)
            {
                row = tbl.AddRow();
               
                for(int j = 0; j < colsCount; ++j)
                {

                    // Adicionar uma tag com um valor na ultima celula da linha
                    if (j == (colsCount - 1))
                    {
                        row[j].Tag = "Valor a Transportar: 200";
                        para = row[j].AddParagraph();
                        para.AddText("200€ *");
                    }
                    else
                        para = row[j].AddParagraph("[Row=" + i + " | Col=" + j + "];"); // Coordenadas da celula só para as preencher com algo e defenição das borders

                    para.Format.Alignment = ParagraphAlignment.Center;
                    row[j].Borders = cellBorders.Clone();
                }
            }
            #endregion Criação do body da tabela

            #endregion Criação das linhas

            // Configuração da tabela
            tbl.LeftPadding = tbl.RightPadding = tbl.TopPadding = tbl.BottomPadding = tblPadding;
            tbl.Rows.Alignment = RowAlignment.Center;
            return doc;
        }


The code I use to find the cells with the value and add it, I got most of this code from a post here on the forum and changed it, I presume I can use code similar to this to find the split table, I just don't know what to look for.

Code:
public static class Extensions
    {
        public static List<DocumentObject> GetDocumentObjectsWithTag(this Document document)
        {
            List<DocumentObject> _objs = new List<DocumentObject>();
            List<double> valoresATransportar = new List<double>();
            DocumentRenderer _renderer = new DocumentRenderer(document);
            _renderer.PrepareDocument();

            int pageCount = _renderer.FormattedDocument.PageCount;
            Unit tableHeight = 0;
            double totalATransportar = 0;
            Table table = null;

            for (int page = 1; page <= pageCount; page++)
            {
                DocumentObject[] docObjects = _renderer.GetDocumentObjectsFromPage(page);
                _renderer.GetRenderInfoFromPage(page);

                if (docObjects != null && docObjects.Length > 0)
                {
                    for (int i = 0; i < docObjects.Length; i++)
                    {
                        if (docObjects[i].GetType() == typeof(Table))
                        {
                            table = (Table
                                )docObjects[i];
                            for (int row = 0; row < table.Rows.Count; row++)
                            {
                                for (int col = 0; col < table.Columns.Count; col++)
                                {
                                    try
                                    {
                                        Cell cell = table[row, col];
                                        if (cell.Tag.ToString().Contains("Valor a Transportar:"))
                                        {
                                            double valor = Convert.ToDouble(cell.Tag.ToString().Split(':')[1].Trim());
                                            totalATransportar += valor;
                                            _objs.Add(cell.Elements[0]);
                                        }
                                    }
                                    catch
                                    {

                                    }
                                }

                                tableHeight += table.Rows[row].Height;

                                if (row == table.Rows.Count - 1)
                                {
                                    // Distancias a levar em conta, a contar com as margens
                                    Unit y = (tableHeight + document.LastSection.PageSetup.TopMargin);
                                    Unit x = (table.Columns.Cast<Column>().Sum(c => c.Width));

                                    // Adicionar na secção onde esta tabela se encontra
                                    TextFrame tf = table.Section.AddTextFrame();
                                    tf.WrapFormat.Style = WrapStyle.Through;

                                    // relatividades do TextFrame
                                    tf.RelativeVertical = RelativeVertical.Paragraph;
                                    tf.RelativeHorizontal = RelativeHorizontal.Character;

                                    // Dimensões
                                    tf.Width = x - 10;
                                    tf.Height = 10;

                                    // Posição absoluta
                                    //tf.MarginLeft = 0f;
                                    tf.MarginTop = 10f;
                                   
                                    var para = tf.AddParagraph(string.Format("A Transportar: {0:N2}€ *", totalATransportar));
                                    para.Format.Alignment = ParagraphAlignment.Right;
                                    para.Format.Font.Size = 5;
                                    //para.Format.Shading.Color = new MigraDoc.DocumentObjectModel.Color(100, 135, 195, 230);
                                }
                            }
                        }
                    }
                }
            }


            Console.WriteLine("valor de teste: " + totalATransportar);
            //Console.ReadKey();

            return _objs;
        }
    }


Thank you in advance.


Attachments:
ValorATransportar.png
ValorATransportar.png [ 63.1 KiB | Viewed 7846 times ]
Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 27, 2019 12:00 pm 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3095
Location: Cologne, Germany
IRlyDunno wrote:
I have a table that I have to know when and if it splits, so that I can add a textframe with the sum value of a columns cell, something like the image attached.
Pages and positions on pages start to exist when the PDF renderer prepares the document.

An approach that should work:
  • Create the document and clone it
  • Prepare the clone with the renderer
  • Find out where to add TextFrames and add them to the original document
  • Create the PDF from the document

Finding out which rows of a table are on which page is possible, but a bit complicated. I did it once, but don't remember the details how I did it.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 27, 2019 12:13 pm 
Offline

Joined: Tue Aug 06, 2019 10:45 am
Posts: 45
So there isn't a direct way for me to know where of if a table splits to another page?


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 27, 2019 12:30 pm 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3095
Location: Cologne, Germany
IRlyDunno wrote:
So there isn't a direct way for me to know where of if a table splits to another page?
Pages do not exist for MigraDoc.
Pages exist for PDF. Page layout is done in the Prepare process.
Layout information is available after the Prepare process.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 27, 2019 1:43 pm 
Offline

Joined: Tue Aug 06, 2019 10:45 am
Posts: 45
Ok, I noticed that I recieve an FormatInfo[] from the GetRenderInfoFromPage(page) method.
So, my question now is, if the array docObjects[] that I get from .GetDocumentObjectsFromPage(page), is 'parallel' with the FormatInfo[].

With this I mean that the FormatInfo[i] belongs to the docObjects[i], is this true and an acceptable form of doing this?
For now I'll try this and take it as a fact, but I just want confirmation if possible!

I also would like to know, of possible, how could I add a textframe to a Specific page, as to, when I find the last row of the table (in the page in question), add the textframe, just below the row, or do I really have to rewrite the document and add the textframe at the right time?

[EDIT]
This is the code I came up with:

Code:
/// this class hold the transported value and the transporting value in a paragraph,
   /// it has the value of the page to know where to add, and 2 flags to tell me if it is transporting or being transported.
   public class ContinuedTextInfo
    {
        private Paragraph text = null;
        private int pageNumber = 0;
        private bool toTransport = false;
        private bool beingTransported = false;

        public Paragraph text        { get { return text; } }
        public int PageNumber        { get { return pageNumber; } }
        public bool ToTransport      { get { return isATransportar; } }
        public bool BeingTransported { get { return isTransportado; } }

        public ContinuedTextInfo(int pageNumber, bool toTransport, Paragraph text)
        {
            this.text = text;
            this.pageNumber = pageNumber;
            this.toTransport = IsATransportar;
            this.beingTransported = !beingTransported;
        }
    }


    public static class Extensions
    {
        public static List<ContinuedTextInfo> GetContinuedText(this Document document, int ColWithValuesIndex)
        {
            List<ContinuedTextInfo> continuedTextList = new List<ContinuedTextInfo>();
            DocumentRenderer _renderer = new DocumentRenderer(document.Clone());
            _renderer.PrepareDocument();
         
         // Paragraph used to reuse the style of a paragraph
            Paragraph styledParagraph = new Paragraph();
            styledParagraph.Format.Alignment = ParagraphAlignment.Right;
            styledParagraph.Format.Font.Size = 5;
            styledParagraph.Format.Font.Name = PdfFontNames.SegoeUI;
            styledParagraph.Font.Italic = true;

         // Values to help with the data lookup
            int pageCount = _renderer.FormattedDocument.PageCount;
            bool isTransporting = false;
            double totalBeingTransported = 0;

         // Objects to hold the value, so they don't need to be re-created every cycle.
            TableFormatInfo tableInfo = null;
            Table table = null;
            Cell cell   = null;

            // Loop through all of the pages
            for (int page = 1; page <= pageCount; ++page)
            {
                DocumentObject[] docObjects = _renderer.GetDocumentObjectsFromPage(page);
                RenderInfo[] info           = _renderer.GetRenderInfoFromPage(page);

                // If there are objects in this page
                if (docObjects != null && docObjects.Length > 0)
                {
                    // Loop through them
                    for (int i = 0; i < docObjects.Length; ++i)
                    {
                        // Each time I found a table
                        if (docObjects[i].GetType() == typeof(Table))
                        {
                            tableInfo = (TableFormatInfo)info[i].FormatInfo;
                            table     = (Table)docObjects[i];

                            if (isTransporting) // If value is being transported from previous page...
                            {
                                Paragraph valorATransportar = styledParagraph;
                                valorATransportar.Add(string.Format("Transporte: {0:N2} *", totalBeingTransported));
                                isTransporting = false;

                                continuedTextList.Add(new ContinuedTextInfo(page, isTransporting, valorATransportar));
                            }
                     
                     // If the table has more rows than the ones on the page
                            if (table.Rows.Count >= tableInfo.EndRow)
                            {
                                isTransporting = true; // If the table is continuing to another page, I have to transport

                        // Cycle through the rows and lookand sum the values on a column
                                for (int r = tableInfo.StartRow; r < tableInfo.EndRow; ++r)
                                {
                           // If the row is header of the table, it doesn't have values
                                    if (table.Rows[r].HeadingFormat)
                                        continue;

                                    cell = table[r, ColWithValuesIndex]; // Get the cell that should have a value
                                    if (cell.Tag != null && cell.Tag.ToString().Contains("Valor a Transportar:")) // If the tag has the right content
                                    {
                                        double valor = Convert.ToDouble(cell.Tag.ToString().Split(':')[1].Trim());
                                        totalBeingTransported += valor;
                                    }
                                }

                                if (isTransporting) // If it will transport, create a new paragraph to be added enventually
                                {
                                    Paragraph valorATransportar = styledParagraph;
                                    valorATransportar.Add(string.Format("A Transportar: {0:N2} *", totalBeingTransported));

                                    continuedTextList.Add(new ContinuedTextInfo(page, isTransporting, valorATransportar));
                                }
                            }
                            else // Else, reset the variable to be reused for another table.
                            {
                                totalBeingTransported = 0;
                            }
                        }
                    }
                }
            }


But now I don't know how to add the paragraphs to an absolute location on the page.

here's what I tried, altough it didn't work:

Code:
        PdfDocumentRenderer renderer = new PdfDocumentRenderer();
        renderer.Document = doc;
        renderer.DocumentRenderer.PrepareDocument();
        renderer.PrepareRenderPages();
        renderer.RenderDocument();

        for(int i = 0; i < continuedCellList.Count; ++i)
        {
            int page = continuedCellList[i].PageNumber;

            if (continuedCellList[i].IsATransportar)
            {
                var gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(renderer.PdfDocument.Pages[page]);
                renderer.DocumentRenderer.RenderObject(gfx, 350, 200, 200, continuedCellList[i].Texto);
            }
            else if(continuedCellList[i].IsTransportado)
            {
                var gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(renderer.PdfDocument.Pages[page]);
                renderer.DocumentRenderer.RenderObject(gfx, 350, 500, 200, continuedCellList[i].Texto);
            }
        }

            renderer.PdfDocument.Save("1_" + "Teste_de_Encontrar_Objetos" + ".pdf");


Thank you in advance.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

Users browsing this forum: Bing [Bot] and 136 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group