關(guān)于全域查找且替換
C#全域操作 Word 查找且替換主要包括如下四個(gè)對(duì)象:
序號(hào) | 對(duì)象 | 說(shuō)明 |
1 | Word.Appication.Selection | 窗格對(duì)象 |
2 | Word.Section.Headers[Word.WdHeaderFooterIndex.wdHeaderFooterPrimary].Range | 頁(yè)眉對(duì)象 |
3 | Word.Section.Footers[Word.WdHeaderFooterIndex.wdHeaderFooterPrimary].Range | 頁(yè)腳對(duì)象 |
4 | Word.Shape.TextFrame.TextRange | 形狀對(duì)象 |
我們需要?jiǎng)?chuàng)建 Word.Find 對(duì)象,對(duì)上述相關(guān)區(qū)域分別進(jìn)行查找替換操作。
![]()
Word應(yīng)用樣本
我們假設(shè)設(shè)計(jì)簡(jiǎn)歷模板的輸出,并查找且替換對(duì)應(yīng)的關(guān)鍵字,如下圖:

其中對(duì)應(yīng)項(xiàng)目的關(guān)鍵字如 {xm}、{xb} 等則為查找且替換的對(duì)象,{grzp} 關(guān)鍵字處我們要處理圖片的插入。
![]()
SqlServer數(shù)據(jù)表部分設(shè)計(jì)樣本
設(shè)計(jì) PersonInfo 數(shù)據(jù)表如下:

CREATE TABLE [dbo].[PersonInfo](
[id] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[sfzh] [varchar](18) NOT NULL,
[xm] [nvarchar](50) NOT NULL,
[xb] [nvarchar](1) NULL,
[grzp] [image] NULL,
CONSTRAINT [PK_PersonInfo] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_PersonInfo] UNIQUE NONCLUSTERED
(
[sfzh] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[PersonInfo] ADD CONSTRAINT [DF_PersonInfo_id] DEFAULT (newid()) FOR [id]
GO
通過(guò)查詢 select sfzh,xm,xb,grzp from PersonInfo where id=xxx 得到DataSet,再取 Tables[0]中的數(shù)據(jù)。
![]()
范例運(yùn)行環(huán)境
操作系統(tǒng): Windows Server 2019 DataCenter
操作系統(tǒng)上安裝 Office Excel 2016
數(shù)據(jù)庫(kù):Microsoft SQL Server 2016
.net版本: .netFramework4.7.1 或以上
開(kāi)發(fā)工具:VS2019 C#
![]()
配置Office DCOM
配置方法可參照我的文章《C# 讀取Word表格到DataSet》進(jìn)行處理和配置。
![]()
設(shè)計(jì)實(shí)現(xiàn)
![]()
組件庫(kù)引入

![]()
實(shí)現(xiàn)原理
我們假設(shè)查詢出表數(shù)據(jù),存入對(duì)應(yīng)的變量,其中將二進(jìn)制字段grzp數(shù)據(jù)寫入到d:\test.jpg生成圖片,示例代碼如下:
DataTable dt=DataSet.Tables[0];
string sfzh = dt.Rows[0]["sfzh"].ToString();
object bt = dt.Rows[0]["grzp"];
byte[] bFile2 = (byte[])bt;
System.IO.File.WriteAllBytes("@d:\test.jpg", bFile2);
string xm = dt.Rows[0]["xm"].ToString();
string xb = dt.Rows[0]["xb"].ToString();
然后我們將其存到二維字符串?dāng)?shù)組 _repls 里,如下代碼:
string[,] _repls = new string[4, 2];
_repls[0, 0] = "{sfzh}";
_repls[0, 1] = sfzh;
_repls[1, 0] = "{xm}";
_repls[1, 1] = xm;
_repls[2, 0] = "{xb}";
_repls[2, 1] = xb;
_repls[3, 0] = "RepalceFromImageFilename_{grzp}";
_repls[3, 1] = "@d:\test.jpg";
其中第一元素存儲(chǔ)要查找的關(guān)鍵字,第二元素存儲(chǔ)要替換的值。注意:替換圖片使用了自定義的RepalceFromImageFilename_ 前綴關(guān)鍵字,則表示值為對(duì)應(yīng)的文件路徑。數(shù)據(jù)準(zhǔn)備完畢后,我們將通過(guò)遍歷數(shù)組對(duì) Word 進(jìn)行查找且替換操作。
![]()
查找且替換的核心代碼
窗格內(nèi)容
示例代碼如下:
WordApp.Options.ReplaceSelection = true;
Word.Find fnd = WordApp.Selection.Find;
for(int i=0;i<_repls.GetLength(0);i++)
{
if (_repls[i, 0] == "" || _repls[i, 0] == null)
{
continue;
}
fnd.ClearFormatting();
string ft = _repls[i, 0];
string replaceType = "";
if (ft.IndexOf("RepalceFromImageFilename_") == 0)
{
ft = ft.Replace("RepalceFromImageFilename_", "");
replaceType = "RepalceFromImageFilename";
}else if (ft.IndexOf("RepalceFromImageFilenameNoDelete_") == 0)
{
ft = ft.Replace("RepalceFromImageFilenameNoDelete_", "");
replaceType = "RepalceFromImageFilenameNoDelete";
}
Object findText = ft;
Object matchCase = false;
Object matchWholeWord = Type.Missing;
Object matchWildcards = false;
Object matchSoundsLike = false;
Object matchAllWordForms = false;
Object forward = true;
Object wrap =Word.WdFindWrap.wdFindContinue;
Object format = false;
Object replaceWith ="";
Object replace =Type.Missing;;
Object matchKashida = Type.Missing;
Object matchDiacritics = Type.Missing;
Object matchAlefHamza = Type.Missing;
Object matchControl = Type.Missing;
while(fnd.Execute(ref findText, ref matchCase, ref matchWholeWord,ref matchWildcards, ref matchSoundsLike, ref matchAllWordForms,
ref forward, ref wrap, ref format, ref replaceWith,ref replace, ref matchKashida, ref matchDiacritics,ref matchAlefHamza, ref matchControl))
{
string r_f=WordApp.Selection.Font.Name.ToString();
if (replaceType == "RepalceFromImageFilename" || replaceType == "RepalceFromImageFilenameNoDelete")
{
if (File.Exists(_repls[i, 1].ToString()))
{
WordApp.Selection.Range.Select();
Word.InlineShape pic = WordApp.Selection.InlineShapes.AddPicture(_repls[i, 1].ToString(), false, true, WordApp.Selection.Range);
if (replConfigs != null)
{
string[] cv = replConfigs[ft].Split('|');
pic.Width = int.Parse(cv[0]);
pic.Height = int.Parse(cv[1]);
}
if (replaceType == "RepalceFromImageFilename")
{
File.Delete(_repls[i, 1].ToString());
}
}
}
else
{
WordApp.Selection.Range.Text = _repls[i, 1].ToString();
}
}
}
頁(yè)眉內(nèi)容
示例代碼如下:
foreach (Word.Section header in WordDoc.Sections)
{
Word.Range headerRange = header.Headers[Word.WdHeaderFooterIndex.wdHeaderFooterPrimary].Range;
Word.Find fnd = headerRange.Find;
for (int i = 0; i < _repls.GetLength(0); i++)
{
if (_repls[i, 0] == "" || _repls[i, 0] == null)
{
continue;
}
fnd.ClearFormatting();
string ft = _repls[i, 0];
string replaceType = "";
if (ft.IndexOf("RepalceFromImageFilename_") == 0)
{
ft = ft.Replace("RepalceFromImageFilename_", "");
replaceType = "RepalceFromImageFilename";
}
else if (ft.IndexOf("RepalceFromImageFilenameNoDelete_") == 0)
{
ft = ft.Replace("RepalceFromImageFilenameNoDelete_", "");
replaceType = "RepalceFromImageFilenameNoDelete";
}
Object findText = ft;
Object matchCase = false;
Object matchWholeWord = Type.Missing;
Object matchWildcards = false;
Object matchSoundsLike = false;
Object matchAllWordForms = false;
Object forward = true;
Object wrap = Word.WdFindWrap.wdFindContinue;
Object format = false;
Object replaceWith = "";
Object replace = Type.Missing; ;
Object matchKashida = Type.Missing;
Object matchDiacritics = Type.Missing;
Object matchAlefHamza = Type.Missing;
Object matchControl = Type.Missing;
while (fnd.Execute(ref findText, ref matchCase, ref matchWholeWord, ref matchWildcards, ref matchSoundsLike, ref matchAllWordForms,
ref forward, ref wrap, ref format, ref replaceWith, ref replace, ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl))
{
string r_f = WordApp.Selection.Font.Name.ToString();
if (replaceType == "RepalceFromImageFilename" || replaceType == "RepalceFromImageFilenameNoDelete")
{
if (File.Exists(_repls[i, 1].ToString()))
{
WordApp.Selection.Range.Select();
Word.InlineShape pic = WordApp.Selection.InlineShapes.AddPicture(_repls[i, 1].ToString(), false, true, headerRange);
if (replaceType == "RepalceFromImageFilename")
{
File.Delete(_repls[i, 1].ToString());
}
}
}
else
{
headerRange.Text = _repls[i, 1].ToString();
}
}
}
}
頁(yè)腳內(nèi)容
示例代碼如下:
foreach (Word.Section footer in WordDoc.Sections)
{
Word.Range footerRange = footer.Footers[Word.WdHeaderFooterIndex.wdHeaderFooterPrimary].Range;
Word.Find fnd = footerRange.Find;
for (int i = 0; i < _repls.GetLength(0); i++)
{
if (_repls[i, 0] == "" || _repls[i, 0] == null)
{
continue;
}
fnd.ClearFormatting();
string ft = _repls[i, 0];
string replaceType = "";
if (ft.IndexOf("RepalceFromImageFilename_") == 0)
{
ft = ft.Replace("RepalceFromImageFilename_", "");
replaceType = "RepalceFromImageFilename";
}
else if (ft.IndexOf("RepalceFromImageFilenameNoDelete_") == 0)
{
ft = ft.Replace("RepalceFromImageFilenameNoDelete_", "");
replaceType = "RepalceFromImageFilenameNoDelete";
}
Object findText = ft;
Object matchCase = false;
Object matchWholeWord = Type.Missing;
Object matchWildcards = false;
Object matchSoundsLike = false;
Object matchAllWordForms = false;
Object forward = true;
Object wrap = Word.WdFindWrap.wdFindContinue;
Object format = false;
Object replaceWith = "";
Object replace = Type.Missing; ;
Object matchKashida = Type.Missing;
Object matchDiacritics = Type.Missing;
Object matchAlefHamza = Type.Missing;
Object matchControl = Type.Missing;
while (fnd.Execute(ref findText, ref matchCase, ref matchWholeWord, ref matchWildcards, ref matchSoundsLike, ref matchAllWordForms,
ref forward, ref wrap, ref format, ref replaceWith, ref replace, ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl))
{
string r_f = WordApp.Selection.Font.Name.ToString();
// WordApp.Selection.Font.Name=r_f;
// WordApp.Selection.Range
// WordApp.Selection.TypeText(_repls[i,1].ToString());
if (replaceType == "RepalceFromImageFilename" || replaceType == "RepalceFromImageFilenameNoDelete")
{
if (File.Exists(_repls[i, 1].ToString()))
{
WordApp.Selection.Range.Select();
Word.InlineShape pic = WordApp.Selection.InlineShapes.AddPicture(_repls[i, 1].ToString(), false, true, footerRange);
if (replaceType == "RepalceFromImageFilename")
{
File.Delete(_repls[i, 1].ToString());
}
}
}
else
{
footerRange.Text = _repls[i, 1].ToString();
}
}
}
}
形狀內(nèi)容
示例代碼如下:
foreach (Word.Shape shape in WordDoc.Shapes)
{
if (shape.TextFrame.HasText == 0)
{
continue;
}
Word.Find fnd = shape.TextFrame.TextRange.Find;
//Word.Find fnd = WordDoc.Content.Find;
for (int i = 0; i < _repls.GetLength(0); i++)
{
if (_repls[i, 0] == "" || _repls[i, 0] == null)
{
continue;
}
fnd.ClearFormatting();
string ft = _repls[i, 0];
string replaceType = "";
if (ft.IndexOf("RepalceFromImageFilename_") == 0)
{
ft = ft.Replace("RepalceFromImageFilename_", "");
replaceType = "RepalceFromImageFilename";
}
else if (ft.IndexOf("RepalceFromImageFilenameNoDelete_") == 0)
{
ft = ft.Replace("RepalceFromImageFilenameNoDelete_", "");
replaceType = "RepalceFromImageFilenameNoDelete";
}
Object findText = ft;
Object matchCase = false;
Object matchWholeWord = Type.Missing;
Object matchWildcards = false;
Object matchSoundsLike = false;
Object matchAllWordForms = false;
Object forward = true;
Object wrap = Word.WdFindWrap.wdFindContinue;
Object format = false;
Object replaceWith = "";
Object replace = Type.Missing; ;
Object matchKashida = Type.Missing;
Object matchDiacritics = Type.Missing;
Object matchAlefHamza = Type.Missing;
Object matchControl = Type.Missing;
while (fnd.Execute(ref findText, ref matchCase, ref matchWholeWord, ref matchWildcards, ref matchSoundsLike, ref matchAllWordForms,
ref forward, ref wrap, ref format, ref replaceWith, ref replace, ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl))
{
string r_f = WordApp.Selection.Font.Name.ToString();
if (replaceType == "RepalceFromImageFilename" || replaceType == "RepalceFromImageFilenameNoDelete")
{
if (File.Exists(_repls[i, 1].ToString()))
{
Word.InlineShape pic = WordApp.Selection.InlineShapes.AddPicture(_repls[i, 1].ToString(), false, true, shape.TextFrame.TextRange);
if (replaceType == "RepalceFromImageFilename")
{
File.Delete(_repls[i, 1].ToString());
}
}
}
else
{
shape.TextFrame.TextRange.Text = _repls[i, 1].ToString();
}
}
}
}
![]()
小結(jié)
1、示例代碼是冗余的寫法,在實(shí)際應(yīng)用中我們需要進(jìn)行優(yōu)化。
2、添加圖片后,代碼默認(rèn)是使用完畢后,刪除圖片文件以釋放空間,我們自定義了 RepalceFromImageFilenameNoDelete_ 前綴關(guān)鍵字,表示使用完畢后不進(jìn)行文件刪除。
3、示例代碼中 Word 表示 using Word=Microsoft.Office.Interop.Word; 的引用。
4、示例代碼 WordDoc 表示對(duì) Word.Document 的引用。
該文章在 2025/1/14 15:39:43 編輯過(guò)