C# OpenXML 修改 word 替換字元

因需要由資料庫資料,替換 word 文字,以提供下載,故選擇 OpenXML 元件進行開發。 

1、需下載 DocumentFormat.OpenXml.dll , 自行 google OpenXml 就會出現下載點。

2、編譯時會出現需參考 WindowsBase.dll , 請自行參考。

程式碼如下:
 

private void button1_Click(object sender, EventArgs e)
{
  string tPath = @"..\1.docx";
  string tOutPath = string.Format(@"..\{0}.docx", DateTime.Now.ToString("yyyyMMddHHmmss"));
  Dictionary <string, string> tReplaceDic = new Dictionary<string,string> ();
  tReplaceDic.Add("§§name§§", "王小明");
  tReplaceDic.Add("§§phone§§", "0912345678");
  tReplaceDic.Add("§§address§§", "台北市忠孝東路1號");
  tReplaceDic.Add("§§company§§", "google公司");

  bool tResult = WordReplace(tPath, tOutPath, tReplaceDic);

  if (tResult == true)
  {
    MessageBox.Show("OK");
  }
  else
  {
    MessageBox.Show("Not OK");
  }
}


private bool WordReplace(string pTemplatePath, string pOutputFilePath, Dictionary<string, string> pReplaceDic)
{
  bool tResultbool = true;

  try
  {
    string tPath = pTemplatePath;
    string tOutPath = pOutputFilePath;
    if (File.Exists(tPath) == true)
    {
      //從範本COPY一份出來
      File.Copy(tPath, tOutPath);

      using (WordprocessingDocument tWordDocument = WordprocessingDocument.Open(tOutPath, true))
      {
        Body tBody = tWordDocument.MainDocumentPart.Document.Body;

        foreach (KeyValuePair<string, string> tKeyVP in pReplaceDic)
        {
          string tSource = tKeyVP.Value;
          string tTarget = tKeyVP.Key;
          char[] tTargetArray = tTarget.ToCharArray();

          foreach (Paragraph tParagraph in tBody.Descendants<Paragraph>())
          {
            //若尋找目標存在於此段落
            if (tParagraph.InnerText.Trim().Contains(tTarget) == true)
            {
              int tIndex = 0;  //Target Index
              int tRunIndex = 0; // 目前 Run 的 Index
              int tStartRun = 0; //啟始的 Run
              string tStartString = string.Empty;
              int tEndRun = 0; //最後的 Run
              string tEndString = string.Empty;
              bool tIsFindStart = false;
              foreach (Run tRun in tParagraph.Descendants<Run>())
              {
                char[] tSourceArray = tRun.InnerText.Trim().ToCharArray();

                bool tIsFind = FindWord(tTargetArray, tSourceArray, ref tIndex);

                if (tIsFind == true)
                {
                  if (tIsFindStart == false)
                  {
                    tIsFindStart = true; //記錄目前有找到Run
                    tStartRun = tRunIndex; //記錄第一個找到的Run
                    tStartString = tTarget.Substring(0, tIndex + 1);
                    tTargetArray = null;
                    tTargetArray = tTarget.Substring(tIndex + 1, tTarget.Length - (tIndex + 1)).ToCharArray();
                    tIndex = 0;

                    if (tTargetArray.Length == 0)
                    {
                      tEndRun = tRunIndex;
                      tEndString = tStartString;
                      break;
                    }
                  }
                  else
                  {
                    string tTempString = new string(tTargetArray);
                    tTargetArray = null;
                    tTargetArray = tTempString.Substring(tIndex + 1, tTempString.Length - (tIndex + 1)).ToCharArray();
                    tIndex = 0;

                    if (tTargetArray.Length == 0)
                    {
                      tEndRun = tRunIndex;
                      tEndString = tTempString;
                      break;
                    }
                   }
                 }
                 else
                 {
                   if (tIsFindStart == true)
                   {
                     tStartRun = -1;
                     tIsFindStart = false;
                     tTargetArray = null;
                     tTargetArray = tTarget.ToCharArray();
                     tIndex = 0;
                     tStartString = string.Empty;
                     tEndString = string.Empty;
                   }
                  }

                  tRunIndex++;
                }

                tRunIndex = 0;
                foreach (Run tRun in tParagraph.Descendants<Run>())
                {
                  if (tRunIndex >= tStartRun && tRunIndex <= tEndRun)
                  {
                    foreach (Text tText in tRun.Descendants<Text>())
                    {
                      if (tRunIndex == tStartRun || tStartRun == tEndRun)
                      {
                        tText.Text = tText.Text.Replace(tStartString, tSource);
                      }
                      else if (tRunIndex == tEndRun)
                      {
                        tText.Text = tText.Text.Replace(tEndString, "");
                      }
                      else
                      {
                        tText.Text = "";
                      }
                    }
                  }
                  tRunIndex++;
                }

                //重新設定一次要尋找的目標
                tTargetArray = tTarget.ToCharArray();
              }
            }
          }

          tWordDocument.MainDocumentPart.Document.Save();
        }
      }
    }
    catch (Exception ex)
    {
      tResultbool = false;
    }

    return tResultbool;
}

private bool FindWord(char[] pTargetArray, char[] pSourceArray, ref int pTargetIndex)
{
  bool tResultBool = true;

  if (pSourceArray.Length > 0)
  {
    for (int i = 0; i < pSourceArray.Length; i++)
    {
      if (pSourceArray[i] == pTargetArray[pTargetIndex])
      {
        if ((pTargetIndex + 1) == pTargetArray.Length || (pTargetIndex + 1) == pSourceArray.Length)
        {
          break;
        }
        pTargetIndex++;
      }
      else
      {
        if ((pTargetIndex + 1) == pTargetArray.Length && (pSourceArray.Length - (pTargetIndex + 1)) == 0)
        {
          tResultBool = false;
          pTargetIndex = 0;
          break;
        }
        else
        {
          //重置 Source Array
          string tTempString = new string(pSourceArray);
          //一次右移一碼
          char[] tSourceArray = tTempString.Substring(1, pSourceArray.Length - 1).ToCharArray();
          //重置目標 index
          pTargetIndex = 0;

          tResultBool = FindWord(pTargetArray, tSourceArray, ref pTargetIndex);
          break;
        }
      }
    }
  }
  else
  {
    tResultBool = false;
    pTargetIndex = 0;
  }

  return tResultBool;
}

小弟相信會有更好的寫法,此為筆記。