WPS 标点替换功能开发记录
在开发过程中,逐步改进了 WPS 标点替换功能。本文将记录从最初遇到的代码问题,到最终实现根据选中文本替换标点符号的全过程。
问题1:标点替换无法一次替换全文
初始代码(部分)
function replaceEnglishPunctuationWithChinese() {
const doc = wps.WpsApplication().ActiveDocument;
const mapping = { ",": ",", ".": "。", "<": "《", ">": "》", "?": "?", "!": "!" };
for (const [eng, chi] of Object.entries(mapping)) {
const find = doc.Content.Find;
find.ClearFormatting();
find.Text = eng;
find.MatchWildcards = true;
find.Execute();
while (find.Found) {
find.Parent.Text = chi;
find.Execute();
}
}
console.log("英文标点替换完成");
}
分析问题
最初,我的想法是替换 WPS 文档中的英文标点为中文标点(或相反),但是在使用 find.Execute() 替换时,每次只能替换一个字符,所以需要多次替换才能完成全文替换,通过 while (find.Found) 来不断执行替换操作。但在WPS中,可能存在一些性能瓶颈,尤其是在大的文档中。这种方式虽然有效,但可以考虑用一次性的批量替换更高效。
优化方案:一次性替换全文
我想到了能够一次性替换文档中的所有标点符号,而不需要多次替换。为此,采用了正则表达式来批量替换文档中的字符。
改进后的代码
/**
* 将文档中的英文标点替换为中文标点
* 例如: ',' -> ',' , '.' -> '。', '<' -> '《', '>' -> '》' 等
*/
function replaceEnglishPunctuationWithChinese() {
const doc = wps.WpsApplication().ActiveDocument;
const mapping = { ",": ",", "。": ".", "《": "<", "》": ">", "?": "?", "!": "!" };
let text = doc.Content.Text;
// 替换文本中的英文标点为中文标点
for (const [eng, chi] of Object.entries(mapping)) {
const regex = new RegExp(escapeRegExp(eng), "g"); // 创建全局正则表达式
text = text.replace(regex, chi);
}
doc.Content.Text = text;
console.log("英文标点替换完成");
}
/**
* 将文档中的中文标点替换为英文标点
* 例如: ',' -> ',' , '。' -> '.' , '《' -> '<' , '》' -> '>' 等
*/
function replaceChinesePunctuationWithEnglish() {
const doc = wps.WpsApplication().ActiveDocument;
const mapping = { ",": ",", "。": ".", "《": "<", "》": ">", "?": "?", "!": "!" };
let text = doc.Content.Text;
// 替换文本中的中文标点为英文标点
for (const [chi, eng] of Object.entries(mapping)) {
const regex = new RegExp(escapeRegExp(chi), "g"); // 创建全局正则表达式
text = text.replace(regex, eng);
}
doc.Content.Text = text;
console.log("中文标点替换完成");
}
通过使用正则表达式,我们能够一次性替换整个文档中的标点符号,大大提高了替换效率。
问题2:英文标点替换出bug
我发现中文标点替换成英文没问题,英文标点替换成中文就没有变化,思考后我知道这是因为通配符导致的问题
字面匹配 vs 正则匹配
-
字面匹配:如果 find.MatchWildcards = false,find.Text 就会查找文本中的确切字符,而不会处理.*? 等特殊字符。没有正则表达式的特殊字符需要考虑。
-
正则匹配:如果 find.MatchWildcards =true,则启用了通配符匹配,这时特殊字符(如 . 或 *)会被当作正则表达式的控制符来处理。如果希望将它们当作字面字符来匹配,就需要使用escapeRegExp 来转义它们。
//逃逸正则特殊字符* 用于防止正则表达式字符冲突
function escapeRegExp(string) {
return string.replace(/[.*+?^=!:${}()|\[\]\/\\]/g, "\\$&");
}
问题3:根据是否选中部分文本决定替换范围
在后续的开发中,我发现一键替换全文的标点符号太过绝对,我希望能够根据用户是否选中部分文本来决定替换的范围。如果选中了部分文本,就只替换选中的部分;如果没有选中文本,则替换整个文档。
解决方案:判断是否有选中内容
通过检查 selection.Start 和 selection.End 来判断是否有选中内容,如果没有选中,则替换整个文档;如果选中,则只替换选中的部分。
修改部分
const doc = wps.WpsApplication().ActiveDocument;
const selection = doc.Application.Selection;
// 获取选中的文本,如果没有选中则使用整个文档
let text = selection.Text;
// 判断是否有选中文本
if (selection.Start === selection.End) {
// 没有选中内容,替换整个文档
text = doc.Content.Text;
}
// 替换标点逻辑(同上)
...
// 如果有选中,替换选中的内容;否则替换整个文档
if (selection.Start !== selection.End) {
selection.Text = text; // 只替换选中的部分
} else {
doc.Content.Text = text; // 替换整个文档
}
总结
通过不断的优化,最终实现了一个可以根据是否选中部分文本来决定替换范围的标点替换功能。整个过程从最初的逐个字符替换,到批量替换,再到根据选中内容替换,逐步提升了功能的完整性和效率。
这个过程不仅解决了实际的开发需求,也让我更好地理解了正则表达式的使用和 WPS API 的一些特性。在今后的开发中,我将继续积累经验,不断优化和提升代码的效率。
1620

被折叠的 条评论
为什么被折叠?



