none
Word Automation - Delays when Adding/Populating Rows in Word Table RRS feed

  • Question

  • Dear Sir/Madam,

    I have an application that populates a Word template from a database.

    It works ok but I have a problem when populating tables in the Word template with a large number of rows. The template itself contains only the table header and an empty first row, the application then add rows to the table and deletes them.

    My problem is that, as more rows are added to the table, the time it takes to add and populate a row grows making the process virtually unusable for large databases.

    For example, if I want to copy 544 rows from a database into a Word table, the first iterations of adding and populating a table take ~200ms, but come the end of the 544 rows, its taking closer to 800ms.

    I am trying to understand why this is the case and what, if anything, I can do to prevent this from happening.

    Please find below the method I use for populating the Word table.

    Many thanks in advance for any suggestions.

    Cheers,

    Scott

        public void insertTable(DataTable tb, string mkName)
        {
         Word.Table wTbl = oWordDoc.Bookmarks.get_Item(mkName).Range.Tables[1];
    
         for (int i = 0; i < tb.Rows.Count; i++)
         {
    
           //If there is no blank rows left in table, add a new row
           if (i >= (wTbl.Rows.Count - 1))
           {
            wTbl.Rows.Add();
           }
    
           for (int j = 0; j < tb.Columns.Count; j++)
           {
            wTbl.Cell(i+2,j+1).Range.Text = tb.Rows[i][j].ToString();
           }
         }
        }
    
    

     

    • Moved by Larcolais Gong Tuesday, July 12, 2011 2:54 AM (From:Visual C# General)
    Monday, July 11, 2011 1:18 PM

Answers

  • Hi Scott

    Mmm. The essence of the article is that there's no way to approach this the way you want with any hopes of significantly improving the speed of execution. To make any difference at all, you'd need to insert an entirely new table. The two possibilities are to put the data in a concatenated string then "ConvertToTable" or to use WordProcessingML or WordOpenXML (both should work) with the InsertXML method.

    Is there something specially significant about the existing table that you hesitate to replace it with an entirely new table?


    Cindy Meister, VSTO/Word MVP
    • Marked as answer by smiffos Wednesday, July 20, 2011 8:50 AM
    Tuesday, July 12, 2011 12:28 PM
    Moderator

All replies

  • Hello,

    Thank you for posting.

    I moved your thread into Word for Dev'er forum. You get more helpful suggestions there.

    Please feel free to let me know if you have any concern.

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, July 12, 2011 2:54 AM
  • Start with this article to understand what's happening and what your options are. If you want to discuss this further, you need to provide us with the version(s) of Word involved

    http://msdn.microsoft.com/en-us/library/aa537149(office.11).aspx


    Cindy Meister, VSTO/Word MVP
    Tuesday, July 12, 2011 6:54 AM
    Moderator
  • Hi Cindy,

    Thanks for the response and the pointer to the article.

    I implemented some of suggestions in the article i.e. using Normal view and switching repagination & screenupdating off, but it had little effect.

    At present, my word template contains the table with the header and a single empty row. My application then inserts the source information into the table one row at a time, creating each new row prior to populating it.

    I realise that this probably isn't very efficient, but I cannot figure out how to change the number of rows in an existing table without adding them one at a time.

    I know you can add a new table and specify the number of rows and columns for the table, but how do you add a number of rows to an existing table. Any ideas?

    I am using VS 2010 with Microsoft Office 2007.

    Many thanks in advance for any further advice.

    Cheers,

    Scott

    Tuesday, July 12, 2011 10:05 AM
  • Hi Scott

    Mmm. The essence of the article is that there's no way to approach this the way you want with any hopes of significantly improving the speed of execution. To make any difference at all, you'd need to insert an entirely new table. The two possibilities are to put the data in a concatenated string then "ConvertToTable" or to use WordProcessingML or WordOpenXML (both should work) with the InsertXML method.

    Is there something specially significant about the existing table that you hesitate to replace it with an entirely new table?


    Cindy Meister, VSTO/Word MVP
    • Marked as answer by smiffos Wednesday, July 20, 2011 8:50 AM
    Tuesday, July 12, 2011 12:28 PM
    Moderator
  • Hi Cindy,

    There is no specific reason why I shouldn't replace the existing table with an entirely new one other than I am fairly new to C# and Word Automation, and the 'add' rows' method is the first solution I came up with.

    If I insert a completely new table, is it easy to update and format the column headers?

    The content of the table exists in a variable of type DataTable. Can you think of a quick way of getting from DataTable to a concatenated string in order to use the "ConvertToTable" method? Would it be as simple as using the ToString method of the datatable variable?

    Thanks again for your help and any further advice.

    Cheers,

    Scott

    Tuesday, July 12, 2011 12:53 PM
  • Hi Scott,

    If automatic column widths are enabled for a table, the constant re-calculation of the column widths after any string manipulation (such as occurs when you add/edit cell conents) will slow down the macro’s execution. The impact can be significant with long tables. To avoid this, either set:
    MyTable.AllowAutoFit = False
    (corresponding to Table|Table Properties|Options|'Automatically resize to fit contents'), or use:
    MyTable.AutoFitBehavior wdAutoFitFixed


    Cheers
    Paul Edstein
    [MS MVP - Word]
    Wednesday, July 13, 2011 2:05 AM
  • Hi Scott

    <<If I insert a completely new table, is it easy to update and format the column headers?>>

    Yes, absolutely no problem. It would be no different than doing it in an existing table. If by "update... the column headers" you mean write the text, I'd do this as part of the string concatenation so that they're part of what you insert. After the table is inserted, apply the formatting you want to the first row.

    It's been a while since I've done anything with ADO, so I hesitate to offer a suggestion about converting a DataTable to a delimited string. And I'm a bit busy at the moment, so I can't take time out to research that for you (much as I'd like to). Best to ask this in a forum that specializes in ADO.NET.

    I'm pretty sure there's a built-in method to convert an array to a delimited string (Split it would be in VBA and I think there's the same or similar in the .NET Framework). So barring a direct conversion I think it's possible to easily put a DataTable in an Array make that a delimited string?


    Cindy Meister, VSTO/Word MVP
    Wednesday, July 13, 2011 10:19 AM
    Moderator
  • Hi Cindy,

    Thanks again for your assistance with this.

    I stripped my code back to generate a concatenated string of the table contents (including the column headers), then created a new table in the Word document using 'ConvertToTable'.

    The improvements were enormous i.e. my 544 row table is created in seconds rather than minutes.

    In my Word template, I kept my original table with desired formatting etc but when populating the template I use 'ConvertToTable' to create a separate table.

    What I would really like to do is copy the table formatting from my template table directly to the new table created using 'ConvertToTable'. If references to both items exist as type Word.Table in my C# code, do you know of a quick way to copy the formatting from one table and apply it to the other?

    Cheers,

    Scott

    Wednesday, July 13, 2011 10:54 AM
  • Hi Scott

    <<If references to both items exist as type Word.Table in my C# code, do you know of a quick way to copy the formatting from one table and apply it to the other?>>

    Mmm, not really... The CopyFormat method (Selection object) might do it. But that wouldn't be my first preference.

    Question back to you: Are the contents of this template static, or are you having to use something that could change dynamically over time?

    If static (you know someone isn't going to be changing it every time you turn around) then I'd be incined to see if creating a TableStyle from that formatting works. Table Styles aren't everything they could/should be, so YMMV, but it would be worth a try.

    The other thing I'd consider would be to set the formatting style of that table as the "default table style" for the document (template). Then that formatting would be applied automatically to a new table you create. Again, that's something you'd have to try and see how well it works for your particular scenario.


    Cindy Meister, VSTO/Word MVP
    Wednesday, July 13, 2011 3:12 PM
    Moderator
  • Hi Scott,

    What is the status of the problem on your side? Does the suggestion help you? If you still show any concern on the thread, just feel free to follow up.
    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, July 20, 2011 3:13 AM