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);
}
}