我尝试从大量旧Word文件中提取文本并将文本放入数据库中。我通过将文本解析为部分,为每个部分创建文本文件,然后进行批量插入来实现此目的。
写这些文件的人最初使用了一些奇怪的字符。在Word中看起来类似于普通的扩展ASCII字符。但是当我开始查看十进制或十六进制代码时,它们不是任何已知字符。
左侧是文档中最初的字符,右侧是从键盘输入的相应ASCII字符。
当我将它们复制并粘贴到vim中时,它看起来像这样:
使用vim查看十进制和十六进制代码,文件如下所示:
Original True ASCII
Dec Hex Dec Hex
61617 f0b1 177 00b1
61666 f0e2 174 00ae
8220 201c 34 22
8221 201d 34 22
我使用了代码here中的一些行:
NextChar = ActiveDocument.Characters(idx)
Dim nBytes As Long
Dim abBuffer() As Byte
nBytes = WideCharToMultiByte(CP_UTF8, 0&, ByVal StrPtr(NextChar), -1, vbNull, 0&, 0&, 0&)
ReDim abBuffer(4)
nBytes = WideCharToMultiByte(CP_UTF8, 0&, ByVal StrPtr(NextChar), -1, ByVal VarPtr(abBuffer(0)), nBytes - 1, 0&, 0&)
使用此方法,VBA返回以下十进制代码(一些是多个字节,用逗号表示):
Original True ASCII
Dec Dec
40 194, 177
40 194, 174
226, 128, 156 34
226, 128, 157 34
我还尝试了Asc
和AscW
。这些在引号上以某种方式正常工作,只返回最后一个字节。但是,由于ActiveDocument.Characters
返回另外两个的括号,它只是像括号一样处理它。
关于这些不同的输出以及如何正确处理这些字符,我有几个问题。
ActiveDocument.Characters
在阅读加号/减号和注册商标符号时会返回括号?194
在使用这些字符时会被置于前面?177
和174
应该分别是点和双箭头。哪个与Word或vim不匹配。但this table似乎同意Word和vim。有多种ASCII编码吗?我认为这是一个标准。刚学会在Word中使用 Alt X 将每个字符更改为其unicode编号。这在原始引号上工作正常,但是当我在原始正/负和商标符号上尝试它时它什么也没做。不确定这些角色的来源。
我尝试保存到文本文件中。加/减和商标符号将无法在西欧(Windows)编码中正确转换。 UTF-8更好但也有问题。 Unicode将转换所有内容,但它会将问题字符转换为前面提到的字符。
我使用Open XML Productivity Tool并直接查看XML和可能的代码来创建这些奇怪的符号。这就是我发现的:
<w:r w:rsidRPr="00EE7521">
<w:rPr>
<w:sz w:val="16" />
</w:rPr>
<w:sym w:font="Symbol" w:char="F0B1" />
和
RunProperties runProperties1 = new RunProperties();
FontSize fontSize2 = new FontSize(){ Val = "16" };
runProperties1.Append(fontSize2);
SymbolChar symbolChar1 = new SymbolChar(){ Font = "Symbol", Char = "F0B1" };
有没有办法在VBA中检测并正确解码SymbolChar
个字符?或者此时的任何其他语言。
答案 0 :(得分:3)
我刚测试了这个简单的宏,它成功地将我们前两个符号(f0b1,f0e2)的实例替换为我的测试文档中的ASCII等价物。它只是在检测到字符来自PUA(专用区域)时清除第一个字节。
Private Sub Strip_PUA()
For idx = 1 To ActiveDocument.Characters.Count
Dim bArr() As Byte
bArr = ActiveDocument.Characters(idx)
If bArr(1) >= &HE0 And bArr(1) <= &HF8 Then
bArr(1) = 0
ActiveDocument.Characters(idx) = bArr
End If
Next
End Sub
您可能必须根据系统的字节顺序和字符的字节数将bArr调整为1以外的值。这也取决于您遇到的字符恰好具有正确的ASCII字节这一事实。情况可能并非总是如此 - 你必须进行调查才能确定。
编辑:转载自this Google Groups discussion。
Sub SymbolsUnprotect()
Dim SelFont, SelCharNum
Selection.Collapse (wdCollapseStart)
Selection.Find.ClearFormatting
With Selection.Find
.Text = "[" & ChrW(61472) & "-" & ChrW(61695) & "]"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
While Selection.Find.Execute
With Dialogs(wdDialogInsertSymbol)
SelFont = .Font
SelCharNum = .CharNum
End With
Selection.Font.Name = SelFont
Selection.TypeText Text:=ChrW(SelCharNum)
' replace the last 2 lines with the following to
' protect symbols from decorative fonts:
' Selection.InsertSymbol _
' Font:=SelFont, _
' CharacterNumber:=SelCharNum, _
' Unicode:=True
Wend
End Sub
这将“取消保护”符号,当受保护时它将显示为“(”(十进制40)字符 - 这是通过Word的Insert > Symbol
对话框插入的符号的默认值。它将允许您正确读取这些字符的字节为f0 **,但是无法准确地告诉你这些字节对应于像Symbol这样的字体,它们在PUA中定义了它们自己的映射。查找这些mappings for conversion into Unicode(链接到包含±(符号177)到(Unicode 177)和®(符号226)到(Unicode 174)的映射的特定字符块。