C big data export word false death error reporting processing method

  • 2020-05-10 18:38:52
  • OfStack

Recent 1 project is 1 winform based reporting system, according to a series of query parameters calculated results, the resulting word documents a format specification, at first (500) data is the data of less than, write speed can also accept, but recently met one problem is that when a large number of data lines, write word process is very slow, CPU directly to 100%, I am the machine configuration is relatively high, 8 + i5CPU G memory, still suspended animation, the problem troubled me for a few days, I've asked google a lot of times, and basically the answer is that word itself is slow and so forth, or the optimization of unmanaged code is slow, but that's ok, at least you can interact with the progress bar, fake death until you report an error, which is absolutely zero tolerance. Tried a lot of methods, including the unmanaged code forced recycling, multi-threading and other ways, and finally failed, of course, huang tian finally solved the problem, my data volume is not particularly huge, more than 4000 lines written into the table, nonsense, directly paste the code:

The usual way to write word form:


private void LoadSectionWord()
        {
           // The temporary directory 
            string filePath = Tools.CreateWordFileDir() + Utils.GetTimeString() + ".doc";
          // will 2 The base file is written to word file 
            sectionWordTools.ByteConvertWord(sectionWordTools.WordContentByTemplateIDAndTemplateTitle(templateId, sectionTitle), filePath);
            try
            {
              //wdc for winWordControl Instance of control 
                wdC.LoadDocument(filePath);
                Microsoft.Office.Interop.Word.Document wd = (Microsoft.Office.Interop.Word.Document)wdC.document;
                Microsoft.Office.Interop.Word.Application wa = wd.Application;//
               // Need to write Word A collection of 
                if (dicList.Count > 0)
                {
                    dicList = dicList.OrderBy(d => d.Key.AnalyteID).ToDictionary(i => i.Key, ii => ii.Value);
                    sectionWordTools.GotoBookMark(wa, "RepeatAnalysisResult");
                    wa.Selection.Copy();// Copy template control 1 a table
                    sectionWordTools.WordReplace("special matrix", wdg.Species.ToLower().Trim() + " " + wdg.Matrix.ToLower().Trim(), true, wd);
                    string analyteTitles = string.Empty;
                    int index = 0;
                    #region Replace Title
                    foreach (KeyValuePair<AnalyteReNameEntity, DataTable> d in dicList)
                    {
                        AnalyteReNameEntity key = d.Key;
                        if (dicList.Count > 2)
                        {
                            if (index.Equals(dicList.Count - 2))
                            {
                                analyteTitles += key.NewAnalyteName + " and ";
                            }
                            else
                            {
                                analyteTitles += key.NewAnalyteName + " , ";
                            }
                        }
                        else if (dicList.Count == 2)
                        {
                            analyteTitles += key.NewAnalyteName + " and ";
                        }
                        else
                        {
                            analyteTitles += key.NewAnalyteName;
                        }
                        index++;
                    }
                    analyteTitles = analyteTitles.Trim().TrimEnd('d').TrimEnd('n').TrimEnd('a').Trim().Trim(',');
                    sectionWordTools.WordReplace("for Abc000", "for " + analyteTitles, true, wd);
                    #endregion
                    int wordTableCount = 0;
                    foreach (KeyValuePair<AnalyteReNameEntity, DataTable> d in dicList)
                    {
                        AnalyteReNameEntity key = d.Key;
                        DataView dv = d.Value.DefaultView;
                        dv.Sort = "Custom ID";
                        DataTable dt = dv.ToTable();
                        #region  To deal with dt
                        if (dt.Columns["analyteid"] != null)
                        {
                            dt.Columns.Remove("analyteid");
                        } if (dt.Columns["id"] != null)
                        {
                            dt.Columns.Remove("id");
                        }
                        if (dt.Columns["reportid"] != null)
                        {
                            dt.Columns.Remove("reportid");
                        }
                        if (dt.Columns["studyid"] != null)
                        {
                            dt.Columns.Remove("studyid");
                        }
                        if (dt.Columns["analyteid"] != null)
                        {
                            dt.Columns.Remove("analyteid");
                        }
                        #endregion
                        // The first 1 a WordTable
                        Microsoft.Office.Interop.Word.Table tb = wd.Tables[wd.Tables.Count];
                        #region  Filling it 
                        if (dt.Rows.Count > 0)
                        {
                            object beforerow = tb.Rows[2];
                            // header 
                            for (int i = 1; i <= dt.Columns.Count; i++)
                            {
                                tb.Cell(1, i).Range.Text = dt.Columns[i - 1].ColumnName;
                            }
                            for (int k = 1; k <= dt.Rows.Count; k++)
                            {
                                // By default on the template 2 There you go. Add the number of rows 
                                if (k <= dt.Rows.Count - 2)
                                {
                                    tb.Rows.Add(ref beforerow);
                                }
                                for (int i = 1; i <= dt.Columns.Count; i++)
                                {
                                    tb.Cell(k + 1, i).Range.Text = dt.Rows[k - 1][dt.Columns[i - 1].ColumnName].ToString();
                                }
                            }
                        }
                        #endregion
                        sectionWordTools.WordReplace("Abc000", key.NewAnalyteName, true, wd);
                        #region  Processing note 
                        string notStr = GetCurrentReassayReason(key.AnalyteID);
                        //notStr = "Reasons for Reassay:\r1). Confirmation Assay\r2). ALQ\rReasons for Reported Conc.:\r1). The only valid result is reported.\r20. Reassay results selected according to procedure defined in study protocol";
                        sectionWordTools.WordReplace("Repeat analysis Tipis", notStr, true, wd);
                        #endregion
                        // Adjust the table according to the content 
                        //tb.AutoFitBehavior(Microsoft.Office.Interop.Word.WdAutoFitBehavior.wdAutoFitContent);
                        // Adjust the table according to the window 
                        //tb.AutoFitBehavior(Microsoft.Office.Interop.Word.WdAutoFitBehavior.wdAutoFitWindow);
                        if (wordTableCount < dicList.Count - 1)
                        {
                            // wa.Selection.TypeParagraph();// enter 
                            wd.Paragraphs.Last.Range.Select();
                            wa.Selection.Paste();
                        }
                        wordTableCount++;
                        #region  Processing overall format 
                        object lefttopstr = tb.Cell(2, 1).Range.Start;
                        object leftbottomend = tb.Cell(tb.Rows.Count, tb.Columns.Count).Range.End;
                        wd.Range(ref lefttopstr, ref leftbottomend).Select();
                        sectionWordTools.AddBorderNoneLineStyle(wa, false, false, true, true, true, true, true, true);
                        #endregion
 
                    }

                }
            }
            catch (Exception ex)
            {
                Tools.RecordErrorList(ex.Message, ex);
            }
        }

The above code is to load the word template through the winwordControl control, and write data into the word table with 1 row and 1 row. The new table is copied and pasted through the bookmark, and then continue to write 1 row and 1 row. When the amount of data is within 500 rows, the speed is acceptable

The improved code mainly USES the idea of paging, paging the collection or datatable, processing 50 lines of data per page, saving to a temporary file after processing, releasing word resources, opening the temporary file, and then continuing to write to the last writing location. The word resource is released to solve the problem of faking errors due to too much written data. I hope it is helpful for friends dealing with word


private void LoadSectionWord()
        {
            string filePath = Tools.CreateWordFileDir() + Utils.GetTimeString() + ".doc";
            // Read the template 
            sectionWordTools.ByteConvertWord(sectionWordTools.WordContentByTemplateIDAndTemplateTitle(templateId, sectionTitle), filePath);
            try
            {
                wdC.LoadDocument(filePath);
                Microsoft.Office.Interop.Word.Document wd = (Microsoft.Office.Interop.Word.Document)wdC.document;
                Microsoft.Office.Interop.Word.Application wa = wd.Application;
                sectionWordTools.GotoBookMark(wa, "TimeConcentrationData");
                wa.Selection.Copy();// Copy template control 1 a table
                string assayLLOQ = ComputerOfPostText.ComputerPostText.GetStudyAssayLLOQResults(this.studyId);
                sectionWordTools.WordReplace("0.0 ng/mL for Abc000", assayLLOQ, true, wd);
                // Get the grouping, only the grouping is counted, the default has been divided into groups, groups can be adjusted 
                List<string> groupList = commonBLL.GetAnalyteGroupList(this.reportId, COMMON_TYPE);
                List<List<AnalyteReNameEntity>> analyteGroupList = new List<List<AnalyteReNameEntity>>();
                #region  determine Table Number of groups 
                foreach (string group in groupList)
                {
                    List<AnalyteReNameEntity> currentGroupList = commonBLL.GetAnalyteReNameList(this.reportId, this.studyId, group);
                    if (currentGroupList.Count > 0)
                    {
                        analyteGroupList.Add(currentGroupList);
                    }
                }
                #endregion
                if (analyteGroupList.Count > 0)
                {
                    int wordTableCount = 0;
                    foreach (List<AnalyteReNameEntity> currentGroupList in analyteGroupList)
                    {
                        // The first 1 a WordTable
                        Microsoft.Office.Interop.Word.Table tb = wd.Tables[wd.Tables.Count];
                        string key = globalBLL.AnalyteAppendString(currentGroupList);
                        // Need to write word The result set 
                        DataTable dt = new DataTable();
                        #region   structure word The column header 
                        foreach (ReportColumnsEntity rc in rceList)
                        {
                            dt.Columns.Add(rc.ReportText, typeof(string));
                        }
                        foreach (AnalyteReNameEntity ar in currentGroupList)
                        {
                            dt.Columns.Add(ar.NewAnalyteName + " Concentration (ng/mL)", typeof(string));
                        }
                        dt.Columns.Add("Comments", typeof(string));
                        #endregion
                        #region  structure Word In the line DataTable
                        for (int i = 0; i < currentGroupList.Count; i++)
                        {
                            DataRow[] rows = dtResult.Select(string.Format(" analyteid={0}", currentGroupList[i].AnalyteID));
                            if (i == 0)
                            {
                                #region i=0, The padding includes the column header 
                                for (int k = 0; k < rows.Length; k++)
                                {
                                    string conc = Utils.EffectiveNumber(rows[k]["concentration"].ToString(), "3");
                                    DataRow dr = dt.NewRow();
                                    foreach (ReportColumnsEntity rc in rceList)
                                    {
                                        if (rc.WatsonText.Equals("concentration"))
                                        {
                                            dr[rc.ReportText] = Utils.EffectiveNumber(rows[k][rc.WatsonText].ToString(), "3");
                                        }
                                        else
                                        {
                                            dr[rc.ReportText] = rows[k][rc.WatsonText].ToString();
                                        }
                                    }
                                    dr["Comments"] = "NA";
                                    dr[currentGroupList[i].NewAnalyteName + " Concentration (ng/mL)"] = conc;
                                    dt.Rows.Add(dr);
                                }
                                #endregion
                            }
                            else
                            {
                                for (int k = 0; k < rows.Length; k++)
                                {
                                    string conc = Utils.EffectiveNumber(rows[k]["concentration"].ToString(), "3");
                                    // Re - assign the analyte concentration column 
                                    dt.Rows[k][currentGroupList[i].NewAnalyteName + " Concentration (ng/mL)"] = conc;
                                }
                            }
                        }
                        DataTable dtTemp = dt.Copy();
                        DataView dv = dt.DefaultView;
                        dv.Sort = "Subject ID";
                        dtTemp = dv.ToTable();
                        dt = dtTemp;
                        #endregion
                        #region  Filling it 
                        if (dt.Rows.Count > 0)
                        {
                            #region  Split cells by column merges 
                            object wordColumnsCount = dt.Columns.Count;
                            object rownum = 1;
                            for (int k = 0; k < 5; k++)
                            {
                                for (int i = 1; i < tb.Columns.Count; i++)
                                {
                                    tb.Cell(k, i).Range.Text = " ";
                                }
                            }
                            // Merge and split   Selection.Cells.Merge
                            for (int i = 1; i <= 4; i++)
                            {
                                object start = tb.Cell(i, 1).Range.Start;
                                object end = tb.Cell(i, 6).Range.End;
                                wd.Range(ref start, ref end).Select();
                                wa.Selection.Cells.Merge();
                            }
                            for (int i = 1; i < 5; i++)
                            {
                                tb.Cell(i, 1).Split(ref rownum, ref wordColumnsCount);
                            }
                            #endregion
                            // Turn off screen updates 
                            wa.ScreenUpdating = false;
                            #region  The filling of the header 
                            // Headers to fill 
                            for (int i = 1; i <= dt.Columns.Count; i++)
                            {
                                tb.Cell(1, i).Range.Text = dt.Columns[i - 1].ColumnName;
                            }
                            #endregion
                            #region  Filling it 
                            #region  paging 
                            object missing = System.Reflection.Missing.Value;
                            object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges; // To solve normal.dot The problem 
                            object beforerow = tb.Rows[3];
                            int dtRowCounts = dt.Rows.Count;//10;//  
                            int columnCount = dt.Columns.Count;
                            int pageSize = 50;
                            // The total number of pages paged 
                            int totalPages = DataUtils.GetPageCounts(dtRowCounts, pageSize);
                            for (int index = 1; index <= totalPages; index++)
                            {
                                tb = wd.Tables[wd.Tables.Count];
                                beforerow = tb.Rows[3 + (index - 1) * pageSize];
                                DataTable pageDt = DataUtils.GetPagedTable(dt, index, pageSize);
                                #region  Add rows and data 
                                for (int k = 2; k < pageDt.Rows.Count + 2; k++)
                                {
                                    // It's already on the template 3 All right, finally 1 Page to add less 3 line 
                                    if (index.Equals(totalPages))
                                    {
                                        if (k < pageDt.Rows.Count - 3)
                                        {
                                            tb.Rows.Add(ref beforerow);
                                        }
                                    }
                                    else
                                    {
                                        tb.Rows.Add(ref beforerow);
                                    }
                                    // Add a row while populating the value of the cell, reduce 1 A full cycle 
                                    for (int i = 1; i <= pageDt.Columns.Count; i++)
                                    {
                                        tb.Cell(k + (index - 1) * pageSize, i).Range.Text = pageDt.Rows[k - 2][pageDt.Columns[i - 1].ColumnName].ToString();
                                    }
                                }
                                #endregion
                                // Fill out PageSize Bar data, save and then reload the population 
                                object savePath = filePath;
                                wd.SaveAs(ref   savePath, ref   missing,
                ref   missing, ref   missing, ref   missing, ref   missing,
                ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                                wa.ScreenUpdating = true;
                                wd = null;
                                wa = null;
                                Thread.Sleep(10);
                                // Reload the 
                                wdC.LoadDocument(filePath);
                                wd = (Microsoft.Office.Interop.Word.Document)wdC.document;
                                wa = wd.Application;
                                wa.ScreenUpdating = false;
                            }
                            #endregion
                            #endregion
                            // Open screen update 
                            //wa.ActiveDocument.ActiveWindow.WindowState = Microsoft.Office.Interop.Word.WdWindowState.wdWindowStateMaximize;
                            wa.ScreenUpdating = true;
                        }
                        #endregion
                        #region Paste Table
                        sectionWordTools.WordReplace("Abc000", key, true, wd);
                        tb = wd.Tables[wd.Tables.Count];
                        // Adjust the table according to the content 
                        tb.AutoFitBehavior(Microsoft.Office.Interop.Word.WdAutoFitBehavior.wdAutoFitContent);
                        // Adjust the table according to the window 
                        tb.AutoFitBehavior(Microsoft.Office.Interop.Word.WdAutoFitBehavior.wdAutoFitWindow);
                        if (wordTableCount < analyteGroupList.Count - 1)
                        {
                            // wa.Selection.TypeParagraph();// enter 
                            wd.Paragraphs.Last.Range.Select();
                            wa.Selection.Paste();
                        }
                        wordTableCount++;
                        #endregion
                    }
                }
            }
            catch (Exception ex)
            {
                Tools.RecordErrorList(ex.Message, ex);
            }
        }


Related articles: