none
How do I change the size of the table, then the chart in a .docx from code? RRS feed

  • Question

  • hi

    Am using OpenXML and the DocumentBuilder to open report documents and get the 1st and last items and put them into a new blank Word.docx

    The problem is how to resize them?  Here is the xml showing the Table,

    <w:document xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14">
      <w:body>
        <w:p w:rsidR="00B53D27" w:rsidRDefault="009E519C">
          <w:r>
            <w:t xml:space="preserve">This paragraph shall constitute the first </w:t>
          </w:r>
          <w:proofErr w:type="spellStart" />
          <w:r>
            <w:t>breadswidth</w:t>
          </w:r>
          <w:proofErr w:type="spellEnd" />
          <w:r>
            <w:t>.</w:t>
          </w:r>
        </w:p>
        <w:tbl>
          <w:tblPr>
            <w:tblStyle w:val="TableGrid" />
            <w:tblW w:w="10800" w:type="dxa" />

    The table width is also found in the reflected code:

     Table table1 = new Table();
    
                TableProperties tableProperties1 = new TableProperties();
                TableStyle tableStyle1 = new TableStyle(){ Val = "TableGrid" };
                TableWidth tableWidth1 = new TableWidth(){ Width = "10800", Type = TableWidthUnitValues.Dxa };
                

    I want to modify the size of the table here, and then resize the chart so they are the same width and will fit 2-wide on the page.

    Here is the general code used to parse one of the report.docx files, there will be 100 or so.  The goal is to squish the table/chart from each report.docx so they will fit 2 wide on a new page;  

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Validation;
    using OpenXmlPowerTools;
    
    namespace DocumentBuilderExample
    {
        class DocumentBuilderExample
        {
            static void Main(string[] args)
            {
                var n = DateTime.Now;
                var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second));
                tempDi.Create();
                string source1 = "../../Source1.docx";
                string source2 = "../../Source1.docx";
                string source3 = "../../templage.docx";
                List<Source> sources = null;
                // Create new document from 10 paragraphs starting at paragraph 5 of Source1.docx
                sources = new List<Source>()
                {
                     new Source(new WmlDocument(source3), 0, 1, true),
                     new Source(new WmlDocument(source1), 0, 2, false),
                     new Source(new WmlDocument(source2), 19, 1, false)
                };
                DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Out1.docx"));
             }
        }
    }
    

    The above code will take my report doc and get the 1st and last item and put that into a new docx file.  but the size is untouched from the original.  

    Using the XElement or by any method known, how could the object(s) be accessed so the size could be modified?

    Tuesday, December 13, 2016 5:17 PM

Answers

  • Hi,

    When do you want to modify the table size? Before or after merging? You could use code like below to edit the table width.

            public static void changeTableWidth(string filePath)
            {
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
                {
                    MainDocumentPart mainDoc = wordDoc.MainDocumentPart;
                    Document doc = mainDoc.Document;
                    Body body = doc.GetFirstChild<Body>();                
                    Table table = body.GetFirstChild<Table>();
                    TableProperties tableProperties = table.GetFirstChild<TableProperties>();
                    TableWidth tableWidth = tableProperties.TableWidth;
                    tableWidth.Width = "10800";
                    tableWidth.Type = TableWidthUnitValues.Dxa;
                }
            }

    To edit the size of a chart is similar, you could compare the file before and after changing to check the object it uses.

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by rogersbra1 Friday, December 16, 2016 10:27 PM
    Wednesday, December 14, 2016 8:41 AM
    Moderator
  • Hi,

    Class Table is in the  DocumentFormat.OpenXml.Wordprocessing.dll. TableProperties and TableWidth are the same.

    Please change

      DocumentFormat.OpenXml.Drawing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Drawing.Table>();

    Into

      DocumentFormat.OpenXml.Wordprocessing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Table>();

     

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by rogersbra1 Monday, December 19, 2016 4:03 PM
    Monday, December 19, 2016 7:20 AM
    Moderator
  • Hi,

    If Run maybe Null, we could directly get the FontSize as Descendant.

    Please test the code below with your file.

       static void accessTableCell(string filePath)
            {
                int i = 0;
                int j = 0;          
                using (DocumentFormat.OpenXml.Packaging.WordprocessingDocument wordDoc = DocumentFormat.OpenXml.Packaging.WordprocessingDocument.Open(filePath, true))
                {
    
                    DocumentFormat.OpenXml.Packaging.MainDocumentPart mainDoc = wordDoc.MainDocumentPart;
                    DocumentFormat.OpenXml.Wordprocessing.Document doc = mainDoc.Document;
                    DocumentFormat.OpenXml.Wordprocessing.Body body = doc.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Body>();
                    DocumentFormat.OpenXml.Wordprocessing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Table>();
                    foreach (DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow in table.Descendants<DocumentFormat.OpenXml.Wordprocessing.TableRow>())
                    {
                        i++;
                        foreach (DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell in tableRow.Descendants<DocumentFormat.OpenXml.Wordprocessing.TableCell>())
                        {
                            j++;
                            DocumentFormat.OpenXml.Wordprocessing.Paragraph para = tableCell.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Paragraph>();
    
                            DocumentFormat.OpenXml.Wordprocessing.FontSize fontSize = para.Descendants<DocumentFormat.OpenXml.Wordprocessing.FontSize>().FirstOrDefault();
                            if (fontSize != null)
                            {
                                Console.WriteLine("The fontsize of Row {0} Column {1} is {2}", i, j,Convert.ToInt32(fontSize.Val)/2 );
                            }
                            else
                            {
                                Console.WriteLine("The fontsize of Row {0} Column {1} is 11", i, j);
                            }             
                        }
                    }                             
                }
            }
    


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by rogersbra1 Wednesday, December 21, 2016 4:11 PM
    Wednesday, December 21, 2016 3:33 AM
    Moderator

All replies

  • Hi,

    When do you want to modify the table size? Before or after merging? You could use code like below to edit the table width.

            public static void changeTableWidth(string filePath)
            {
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
                {
                    MainDocumentPart mainDoc = wordDoc.MainDocumentPart;
                    Document doc = mainDoc.Document;
                    Body body = doc.GetFirstChild<Body>();                
                    Table table = body.GetFirstChild<Table>();
                    TableProperties tableProperties = table.GetFirstChild<TableProperties>();
                    TableWidth tableWidth = tableProperties.TableWidth;
                    tableWidth.Width = "10800";
                    tableWidth.Type = TableWidthUnitValues.Dxa;
                }
            }

    To edit the size of a chart is similar, you could compare the file before and after changing to check the object it uses.

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by rogersbra1 Friday, December 16, 2016 10:27 PM
    Wednesday, December 14, 2016 8:41 AM
    Moderator
  • Gets an error

    Not sure what type to use

     var rrx =  Path.Combine(tempDi.FullName, "Out1.docx");
                DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Out1.docx"));
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(rrx, true))
                {
                    MainDocumentPart mainDoc = wordDoc.MainDocumentPart;
                    Document doc = mainDoc.Document;
                    Body body = doc.GetFirstChild<Body>();
                    DocumentFormat.OpenXml.Drawing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Drawing.Table>();
       error=>      TableProperties tableProperties = table.GetFirstChild<TableProperties>();
                    TableWidth tableWidth = tableProperties.TableWidth;
                    tableWidth.Width = "800";
                    tableWidth.Type = TableWidthUnitValues.Dxa;
    An unhandled exception of type 'System.NullReferenceException' occurred in DocumentBuilder01.exe

    Additional information: Object reference not set to an instance of an object.


    • Edited by rogersbra1 Friday, December 16, 2016 10:39 PM
    Friday, December 16, 2016 10:34 PM
  • Hi,

    Class Table is in the  DocumentFormat.OpenXml.Wordprocessing.dll. TableProperties and TableWidth are the same.

    Please change

      DocumentFormat.OpenXml.Drawing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Drawing.Table>();

    Into

      DocumentFormat.OpenXml.Wordprocessing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Table>();

     

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by rogersbra1 Monday, December 19, 2016 4:03 PM
    Monday, December 19, 2016 7:20 AM
    Moderator
  • thank you SO MUCH.  The item now drops onto the page with the width changed.

    But, the original table is about 6.5" wide x 2" tall.  Just a title and details really. 

    When I said make the width some small size, its now .75" wide and is wrapping down the page, 2 full pages + 2" of the 3rd page.  nice to know it can do this. 

    But I really needed it 'SCALED' so that it keeps the W x L ratio, is this even possible?  I thought I had done this by select and grabbing a corner and resizing it.  Now?  the only part that can be changed is the width;  

    Is it that each and every last parameter has to be set individually? every font size of every sentence?

    Is there any way to copy this as a blob and resize it?

    And it stepped on the formatting of the Bar Chart, from just looking at the resulting page.  It could be that the formatting was over-ridden; 

    but thats a secondary issue, it just changed the colors of my bar chart, they seem to be proportioned right

    thanks


    • Edited by rogersbra1 Monday, December 19, 2016 5:28 PM
    Monday, December 19, 2016 4:19 PM
  • ok seems like just the font is the problem.  I have 2 different font sizes, the first part of the table is the title with 24pt font, the other has 14pt font for the next 4+ cells

    How to drill into the font settings??

    Monday, December 19, 2016 7:29 PM
  • Hi,

    You could test the code below to access the table cell and output the fontsize.

    If you keep the default fontsize (11), the value are unable to output.

    If you change it into 10, the value would be 20. (Twice of the display value)

            static void accessTableCell(string filePath)
            {
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
                {
                    MainDocumentPart mainDoc = wordDoc.MainDocumentPart;
                    Document doc = mainDoc.Document;
                    Body body = doc.GetFirstChild<Body>();
                    DocumentFormat.OpenXml.Wordprocessing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Table>();
                    foreach (TableRow tableRow in table.Descendants<TableRow>())
                    {
                        foreach (TableCell tableCell in tableRow.Descendants<TableCell>())
                        {
                            Paragraph para = tableCell.GetFirstChild<Paragraph>();
                            Run run = para.GetFirstChild<Run>();
                            RunProperties runPro = run.Descendants<RunProperties>().FirstOrDefault();
                            if (runPro!=null)
                            {
                                Console.WriteLine(runPro.FontSize.Val);
                            }                 
                        }
                    }                             
                }
            }

    If you have new issues, I suggest you post new threads. Thanks for your understanding.

    Besides, I would suggest you download Open XML SDK Tool to generate code, you could download it from https://www.microsoft.com/en-us/download/details.aspx?id=30425

    The steps to use Open XML SDK Tool:

    1. Create two documents with one is original file and one is the target file;

    2. Use Open XML SDK 2.5 productivity Tool for Microsoft Office

    3. Click the Compare Files, generate the code, and then you could get the code what you want

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, December 20, 2016 7:54 AM
    Moderator
  •    foreach (TableRow tableRow in table.Descendants<TableRow>())

    TableRow ??  What namespace please? 

    DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow
    

    RunProperties runPro  this line fails with a null reference exception, but Paragraph para is populated just fine, Run run = para.GetFirstChild<Run>() is null

    I have tried all 3 of the namespaces

    The SDK productivity tool, thanks, yes I use that tool constantly.  the difficult part is understanding the structure of the document to be able to 'get' the needed part.

    the sdk tool will show the hierarchy, but to make the method to go in?  this is not easy. 

    Tuesday, December 20, 2016 3:14 PM
  • Hi,

    If Run maybe Null, we could directly get the FontSize as Descendant.

    Please test the code below with your file.

       static void accessTableCell(string filePath)
            {
                int i = 0;
                int j = 0;          
                using (DocumentFormat.OpenXml.Packaging.WordprocessingDocument wordDoc = DocumentFormat.OpenXml.Packaging.WordprocessingDocument.Open(filePath, true))
                {
    
                    DocumentFormat.OpenXml.Packaging.MainDocumentPart mainDoc = wordDoc.MainDocumentPart;
                    DocumentFormat.OpenXml.Wordprocessing.Document doc = mainDoc.Document;
                    DocumentFormat.OpenXml.Wordprocessing.Body body = doc.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Body>();
                    DocumentFormat.OpenXml.Wordprocessing.Table table = body.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Table>();
                    foreach (DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow in table.Descendants<DocumentFormat.OpenXml.Wordprocessing.TableRow>())
                    {
                        i++;
                        foreach (DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell in tableRow.Descendants<DocumentFormat.OpenXml.Wordprocessing.TableCell>())
                        {
                            j++;
                            DocumentFormat.OpenXml.Wordprocessing.Paragraph para = tableCell.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Paragraph>();
    
                            DocumentFormat.OpenXml.Wordprocessing.FontSize fontSize = para.Descendants<DocumentFormat.OpenXml.Wordprocessing.FontSize>().FirstOrDefault();
                            if (fontSize != null)
                            {
                                Console.WriteLine("The fontsize of Row {0} Column {1} is {2}", i, j,Convert.ToInt32(fontSize.Val)/2 );
                            }
                            else
                            {
                                Console.WriteLine("The fontsize of Row {0} Column {1} is 11", i, j);
                            }             
                        }
                    }                             
                }
            }
    


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by rogersbra1 Wednesday, December 21, 2016 4:11 PM
    Wednesday, December 21, 2016 3:33 AM
    Moderator
  • yes it runs;  I changed the Console.Writeline to 

    System.Diagnostics.Debug.WriteLine

    then it shows up in the Output window.

    The fontsize of Row 1 Column 1 is 24
    The fontsize of Row 2 Column 2 is 24
    The fontsize of Row 2 Column 3 is 4
    The fontsize of Row 2 Column 4 is 24
    The fontsize of Row 2 Column 5 is 24
    The fontsize of Row 3 Column 6 is 12
    The fontsize of Row 3 Column 7 is 12
    The fontsize of Row 3 Column 8 is 12
    The fontsize of Row 3 Column 9 is 12
    

    Wednesday, December 21, 2016 3:04 PM
  • I cannot format the font size of all items, only some of them.  When I try this code, only some are changed.  Im realizing now that the other part of the table are content controls.   These fonts dont change at all.

    with this

    RunProperties runprop = new RunProperties();
                    Run run = new Run();
                    Run run2 = new Run();
                    FontSize fonz = new FontSize();
                    RunProperties runprop2 = new RunProperties();
                    RunFonts runf = new RunFonts();
    
                    foreach (DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow in table.Descendants<DocumentFormat.OpenXml.Wordprocessing.TableRow>())
                    {
                        i++;
                        foreach (DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell in tableRow.Descendants<DocumentFormat.OpenXml.Wordprocessing.TableCell>())
                        {
                            j++;
                            DocumentFormat.OpenXml.Wordprocessing.Paragraph para = tableCell.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Paragraph>();
                            run = para.GetFirstChild<Run>();
    
                            if (run != null)
                            {
                                fonz =  run.Descendants<DocumentFormat.OpenXml.Wordprocessing.FontSize>().FirstOrDefault();
                                fonz.Val = "6";
                            }
    					}
    				}
    						

    it will change the non content control values to font size 3?   its very tiny, if its 6 its just small.

    I do not know how to 'address' the various parts of the document

    Thursday, December 22, 2016 10:15 PM
  • Hi,

    If using Run as the parent to get the fontsize, it maybe cause null reference exception.

    I suggest you use    DocumentFormat.OpenXml.Wordprocessing.FontSize fontSize = para.Descendants<DocumentFormat.OpenXml.Wordprocessing.FontSize>().FirstOrDefault();

    I could edit its fontsize using the code even it is in the content control.

    If it does not work, please post a new thread, we could focus on the specific issue.

    If possible, it would be helpful if you could share a sample file with us, because we have no idea about your table structure or other information which may cause issues.

    Thanks for your understanding.

    Regards.

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, December 23, 2016 8:25 AM
    Moderator