PDFsharp & MigraDoc Foundation https://forum.pdfsharp.net/ |
|
How to Find Tables That Split To Next Page? https://forum.pdfsharp.net/viewtopic.php?f=2&t=4022 |
Page 1 of 1 |
Author: | IRlyDunno [ Fri Sep 27, 2019 11:09 am ] | ||
Post subject: | How to Find Tables That Split To Next Page? | ||
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.
|
Author: | Thomas Hoevel [ Fri Sep 27, 2019 12:00 pm ] |
Post subject: | Re: How to Find Tables That Split To Next Page? |
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:
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. |
Author: | IRlyDunno [ Fri Sep 27, 2019 12:13 pm ] |
Post subject: | Re: How to Find Tables That Split To Next Page? |
So there isn't a direct way for me to know where of if a table splits to another page? |
Author: | Thomas Hoevel [ Fri Sep 27, 2019 12:30 pm ] |
Post subject: | Re: How to Find Tables That Split To Next Page? |
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. |
Author: | IRlyDunno [ Fri Sep 27, 2019 1:43 pm ] |
Post subject: | Re: How to Find Tables That Split To Next Page? |
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. |
Page 1 of 1 | All times are UTC |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |