what we tried as is working for us
- looping through the doc.paragraphs
- inside the loop we are reading the field code
-- the field is represented as
{INCLUDEPICTURE "M:\NVCSync\Testing 7.16.2020.1\Hotel Excel 7.16.1\ExcelTables\T_TestSum.emf"}
so for example we have image like T_TestSum.emf
3.after finding image we are selecting that image range, deleting it and adding the field again.(so that the refeshed image is updated)
Word.Field field = r.Fields.Add(r, Word.WdFieldType.wdFieldIncludePicture, "\"" + vtablelocation.Replace(@"\", @"\") + "\"", preserveformatting);
The above logic works for us, but we have performance bottle neck.
for 200+ images its taking over 120 secs to update.
other ways msdn suggests is
- select all fields in documents and update each field.
doc.Range(ref start, ref end).Select();
try
{
foreach (Word.Field field in doc.Fields)
{
field.UpdateSource();
}
}
catch (Exception ex)
{
}
the above code works for smaller documents, images update quickly.
it fails to update the images if documents are bigger(we didnt get any errors)
- we tried to use async await way of updating the fields but its giving worst performance.
3.parallel.foreach seems to be working but with larger file and many images to update it fails giving us ContextSwitchDeadlock error.
private static async Task UpdateDocumentTableswithouttasking()
{
Word.Application appW = Globals.ThisAddIn.Application;
Word.Document doc = appW.ActiveDocument;
doc.Fields.ToggleShowCodes();
try
{
Microsoft.Office.Interop.Word.Paragraphs DocPar = doc.Paragraphs;
foreach (var par in DocPar)
{
Word.Paragraph p = (Word.Paragraph)par;
string s = p.Range.Text.ToString();
Word.Range pb = p.Range;
if (!String.IsNullOrEmpty(s) && (s.Contains("INCLUDEPICTURE")) || (s.Contains("DOCVARIABLE") && s.Contains("PICTURECUSTOM")) && s != "\r")
{
var alignment = p.Range.ParagraphFormat.Alignment;
Word.WdColorIndex color = p.Range.HighlightColorIndex;
List<DocumentTables> lstDocTables = new List<DocumentTables>();
List<DocumentVars> lstDocFields = new List<DocumentVars>();
string[] arr = new string[] { };
string[] arrDocVarsAndPictures = new string[] { };
if (s.Contains("LINK"))
{
arrDocVarsAndPictures = s.Split(new string[] { "LINK" }, StringSplitOptions.None);
}
else
{
arrDocVarsAndPictures = s.Split(new string[] { "DOCVARIABLE" }, StringSplitOptions.None);
}
for (int cnt = arrDocVarsAndPictures.Length - 1; cnt >= 0; cnt--)
{
string strArr = arrDocVarsAndPictures[cnt].ToString();
string[] ArrwithImages = strArr.Split(new string[] { "INCLUDEPICTURE" }, StringSplitOptions.None);
if (ArrwithImages.Length > 0)
{
for (int cntImages = ArrwithImages.Length - 1; cntImages >= 0; cntImages--)
{
string strArrWithImages = ArrwithImages[cntImages].ToString();
//This means the field is for picture and used when mapping picture or showing error message.
if (strArrWithImages.Contains("T_") || strArrWithImages.Contains("t_"))
{
try
{
string pattern = "\"";
string SelectedField = "";
if (strArrWithImages.Contains("T_"))
{
int i = strArrWithImages.IndexOf("T_");
SelectedField = strArrWithImages.Substring(i + 0);
}
else if (strArrWithImages.Contains("t_"))
{
SelectedField = strArrWithImages.Substring(strArrWithImages.IndexOf("t_") + 0);
}
string[] arrF = SelectedField.Split(new string[] { pattern }, StringSplitOptions.None);
string fieldName = arrF[0].Trim().Replace(strFileExtension, "").Replace(".jpg", "");
var wrksht = "";
if (strArrWithImages.Contains("Swrksht_"))
{
int i = strArrWithImages.IndexOf("Swrksht_");
wrksht = strArrWithImages.Substring(i + 0);
wrksht = wrksht.Split(new string[] { "_" }, StringSplitOptions.None)[1];
if (wrksht == "T" && fieldName.Contains("_"))
{
wrksht = "";
}
}
foreach (Word.Field myMergeField in p.Range.Fields)
{
Word.Range rngFieldCode = myMergeField.Code;
string fieldText = rngFieldCode.Text;
string pattern1 = "\"";
string SelectedField1 = "";
if (fieldText.Contains("T_"))
{
int i = fieldText.IndexOf("T_");
SelectedField1 = fieldText.Substring(i + 0);
}
else if (fieldText.Contains("t_"))
{
SelectedField1 = fieldText.Substring(fieldText.IndexOf("t_") + 0);
}
if (SelectedField1.Contains("\\t"))
{
pattern1 = "\\t";
}
string[] arrF1 = SelectedField1.Split(new string[] { pattern1 }, StringSplitOptions.None);
string fieldName1 = arrF1[0].Trim().Replace(strFileExtension, "").Replace(".jpg", "");
if (fieldName == fieldName1)
{
myMergeField.Select();
Word.Range found = Globals.ThisAddIn.Application.Selection.Range;
Word.Selection s1 = Globals.ThisAddIn.Application.Selection;
s1.Range.Delete();
Word.Range r = Globals.ThisAddIn.Application.ActiveDocument.Range(found.Start, found.Start);
try
{
r.ParagraphFormat.Alignment = alignment;
}
catch (Exception ex)
{
}
//r.Select();
Globals.ThisAddIn.Application.Selection.Font.ColorIndex = Word.WdColorIndex.wdAuto;
TableInfo t = new TableInfo();
try
{
if (String.IsNullOrEmpty(wrksht))
{
t = ThisAddIn.lstTables.OrderBy(z => z.workSheetName).Where(x => x.Tablename == fieldName).FirstOrDefault();
}
else
{
t = ThisAddIn.lstTables.Where(x => x.Tablename == fieldName && x.worksheetCodename == wrksht).FirstOrDefault();
}
if (t != null)
{
if (!String.IsNullOrEmpty(t.Tablename))
{
//myMergeField.Update();
found.Font.ColorIndex = Word.WdColorIndex.wdBlack;
var vtablelocation = t.TableLocation.Replace("Swrksht_", "Swrksht_" + t.worksheetCodename + "_").Replace("Swrksht__", "Swrksht_").Replace("__", "_");
Word.Field field = r.Fields.Add(r, Word.WdFieldType.wdFieldIncludePicture, "\"" + vtablelocation.Replace(@"\", @"\\").Replace(strFileExtension, strFileExtension) + "\"", preserveformatting);
if (t.ApplySizing == 1)
{
try
{
field.InlineShape.Height = (float)t.height;
}
catch
{
}
try
{
field.InlineShape.Width = (float)t.width;
}
catch
{
}
}
}
}
}
catch (Exception ex)
{
}
break;
}
}
}
catch (Exception ex)
{
}
}
}
}
}
//}
}
}
}
catch (Exception ex)
{
log.Error("\r\n" + "Error: Error occured while updating tables" + "\r\n" + ex);
}
doc.Fields.ToggleShowCodes();
foreach (Word.Field field in doc.Fields)
{
var x = field.ShowCodes;
if (x)
{
field.ShowCodes = false;
}
}
}