ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 21603|回复: 21

[分享] Word文档的中文字词频统计

[复制链接]

TA的精华主题

TA的得分主题

发表于 2012-3-10 14:15 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 sylun 于 2012-6-13 18:22 编辑

统计中文字词频的相关帖子已有不少,昨晚用words集合对象提取中文词语时发现提取结果有时出现异常,原因主要是语法和拼写不规范所致,具体来说主要是汉字后面带半角空格或不间断空格,也有引号的问题。经过滤,异常现象有效避免。现将代码放上,也许还有其他异常情况,各位如有兴趣请测试测试,以便改进。
  1. Sub ChineseCharCounting()
  2.     '统计汉字的字词频,并按降序排序
  3.     '中文词语的判断与Word的词典关联
  4.     Dim a As Byte
  5.     Dim n As Long
  6.     Dim filetext As String
  7.     Dim d
  8.     Dim Wd As Range
  9.     Dim W As Range
  10.     Dim b
  11.     Dim c() As String
  12.     Dim i As Long
  13.     Dim temp As String
  14.     Dim st As Single
  15.    
  16.     a = MsgBox("词频统计请按“是”,字频统计请按“否”", vbYesNo, "中文字词频统计")
  17.     st = Timer
  18.     n = ActiveDocument.Content.ComputeStatistics(wdStatisticFarEastCharacters)
  19.     Set d = CreateObject("Scripting.Dictionary")
  20.     If a = vbYes Then
  21.         For Each Wd In ActiveDocument.Words
  22.             With Wd
  23.                 If .Text Like "[一-龥]*" And Len(.Text) > 1 Then
  24.                     If .Text Like "*[!一-龥]*" = False Then
  25.                         d(.Text) = d(.Text) + 1
  26.                     Else
  27.                         For i = 1 To Len(.Text)
  28.                             If Mid(.Text, i, 1) Like "[!一-龥]" Then Exit For
  29.                         Next
  30.                         With .Duplicate
  31.                             .End = .Start + i - 1
  32.                             For Each W In .Words
  33.                                 With W
  34.                                     If Len(.Text) > 1 Then
  35.                                         If Right(.Text, 1) Like "[!一-龥]" Then .End = .End - 1
  36.                                         d(.Text) = d(.Text) + 1
  37.                                     End If
  38.                                 End With
  39.                             Next
  40.                         End With
  41.                     End If
  42.                 End If
  43.             End With
  44.         Next
  45.     Else
  46.         filetext = ActiveDocument.Content.Text
  47.         For i = 1 To Len(filetext)
  48.             temp = Mid(filetext, i, 1)
  49.             If temp Like "[一-龥]" Then d(temp) = d(temp) + 1
  50.         Next
  51.     End If
  52.     b = d.keys
  53.     ReDim c(UBound(b))
  54.     For i = 0 To UBound(b)
  55.         c(i) = b(i) & vbTab & d(b(i))
  56.     Next
  57.     With Documents.Add.Content
  58.         .Text = "文档共有" & n & "个中文字符。共提取到" & d.Count _
  59.             & IIf(a = 6, "个中文词语", "个不同的汉字") & ",其出现次数分别为:" & vbCrLf & Join(c, vbCrLf)
  60.         .Parent.DefaultTabStop = .Characters.First.Font.Size * 6
  61.         .MoveStart wdParagraph
  62.         .Sort , 2, wdSortFieldNumeric, wdSortOrderDescending, 1, , , , , , wdSortSeparateByTabs
  63.     End With
  64.     MsgBox "提取完毕。用时" & Format(Timer - st, "0") & "秒。"
  65. End Sub
复制代码
注:已对代码进行了首次修改,见10楼。

TA的精华主题

TA的得分主题

发表于 2012-3-10 22:07 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2012-3-11 01:37 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
    谢谢楼主!不好意思,因水平太低,修改、添加、测试费了一个半小时,程序运行没有发现问题,样稿不大,但是是有手动换行符和不间断字符的文本,故意添加了一些半角、全角空格和制表符。有两点建议:一是统计结果最后不必出现提示消息框(及运行时间),这样给人以干净利落的感觉(现在代码也是喜欢能减一行就减一行,声明能在一行就在一行,行数太多显得程序太大);二是提取的汉字词语长度建议仅为二、三、四、五字词为宜,多了没有必要(类似:工作、办公室、与时俱进、民主集中制,再长就没有统计的必要了)。我略微修改的代码如下(只是提示信息和最后加了个表格,主体程序看不懂也未改动——顺便请解释一下我的那个帖子:正文四号14磅,则首行缩进为0.99厘米中的公式 2*14*2.54/72=0.99 每个数字是啥意思,3Q!):

Sub 词频统计()
    Dim a As Byte, n As Long, filetext As String, d, Wd As Range, W As Range, b, c() As String, i As Long, temp As String
    a = MsgBox("请选择——是:词频统计    否:字频统计", vbYesNo + vbExclamation, "中文字词频统计")
    n = ActiveDocument.Content.ComputeStatistics(wdStatisticFarEastCharacters)
    Set d = CreateObject("Scripting.Dictionary")
    If a = vbYes Then
        For Each Wd In ActiveDocument.Words
            With Wd
                If .Text Like "[一-龥]*" And Len(.Text) > 1 Then
                    If .Text Like "*[!一-龥]*" = False Then
                        d(.Text) = d(.Text) + 1
                    Else
                        For i = 1 To Len(.Text)
                            If Mid(.Text, i, 1) Like "[!一-龥]" Then Exit For
                        Next
                        With .Duplicate
                            .End = .Start + i - 1
                            For Each W In .Words
                                With W
                                    If Len(.Text) > 1 Then
                                        If Right(.Text, 1) Like "[!一-龥]" Then .End = .End - 1
                                        d(.Text) = d(.Text) + 1
                                    End If
                                End With
                            Next
                        End With
                    End If
                End If
            End With
        Next
    Else
        filetext = ActiveDocument.Content.Text
        For i = 1 To Len(filetext)
            temp = Mid(filetext, i, 1)
            If temp Like "[一-龥]" Then d(temp) = d(temp) + 1
        Next
    End If
    b = d.keys
    ReDim c(UBound(b))
    For i = 0 To UBound(b)
        c(i) = b(i) & vbTab & d(b(i))
    Next
    With Documents.Add.Content
        .Text = IIf(a = 6, "词频统计", "字频统计") & "结果:文档共有" & n & "个中文字符,提取到" & d.Count _
            & IIf(a = 6, "个中文词语", "个不同的汉字") & ",其出现次数分别为:" & vbCrLf & Join(c, vbCrLf)
        .Parent.DefaultTabStop = .Characters.First.Font.Size * 6
        .MoveStart wdParagraph
        .Sort , 2, wdSortFieldNumeric, wdSortOrderDescending, 1, , , , , , wdSortSeparateByTabs
    End With
    ActiveDocument.Paragraphs(1).Range.Bold = True
    ActiveDocument.Range(Start:=ActiveDocument.Paragraphs(2).Range.Start, End:=ActiveDocument.Paragraphs.Last.Range.End).Select
    Selection.ConvertToTable Separator:=wdSeparateByTabs
    Selection.Tables(1).Style = "网格型"
    Selection.HomeKey Unit:=wdStory
End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-3-11 09:59 | 显示全部楼层
413191246se兄这样改也未尝不可,只是这样的改动对代码的直观性和测试的便捷性有所影响。我想关键的还是代码运行的适应性、提取结果的准确性或合理性和提取速度究竟如何。至于建议提取的汉字词语长度仅为二、三、四、五字词,我想word词典中超过4个字的词语不会很多(自行添加进去的除外),如果提取结果有这样的条目,且明显不是一个相对固定的词,则说明提取是不准确的或不合理的,有改进的必要。请老兄多提这方面的意见。

TA的精华主题

TA的得分主题

发表于 2012-3-11 10:12 | 显示全部楼层
谢谢!我以前经常练习打字,有一个《人民日报词频统计资料》的词频统计清单,也有一些自己加入的一些常用词,如果需要我可以截取高频的一些词作为附件上传。另外,词频统计是否是以二字词最先统计呢?如果以二、三、四、五字词来统计(五字词省略也可),就不必来那些拼凑的长词了。——原来运行时间也是为了观察一下提取速度,那还是采用原来的方案吧!——还有,假设我把旧代码“精简、优化”一下(其实也不会啥优化),可否有现成的程序(过程)运行时间测试的语句段或程序呢?

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-3-11 10:37 | 显示全部楼层
词频统计是否是以二字词最先统计呢?

不知是什么意思?如果只统计二字词,可修改一下代码,只是要注意,原来超过两个字的词语不应忽略,应重新考虑是否可再拆分出二字词的问题,这涉及到统计数字的准确性。
另外,所提的关于测试语句的问题,我想在此帖讨论不是很合适。

TA的精华主题

TA的得分主题

发表于 2012-3-11 14:39 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
收藏,学习学习

TA的精华主题

TA的得分主题

发表于 2012-3-11 16:21 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
这个当是论坛上最快的一个,{:soso_e179:}

TA的精华主题

TA的得分主题

发表于 2012-6-13 14:30 | 显示全部楼层
代码统计是不准确的,具体问题请见附件。

文档共有1891个中文字符共提取到310个中文词语,其出现次数分别为:
生源        59
减肥        58
市场价        16
更多        14
商品        14
减肥药        12
颗粒        12
产品        11
排行        10
......

生源和减肥统计的数据与实际偏差很大。
作者能否再看看。

词频统计字词查找.rar

44.29 KB, 下载次数: 181

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-6-13 18:16 | 显示全部楼层
FENGJUN 发表于 2012-6-13 14:30
代码统计是不准确的,具体问题请见附件。

文档共有1891个中文字符共提取到310个中文词语,其出现次数分别 ...

是不很准确,主要原因是文档有语法和拼写错误时可能会导致遍历Words集合对象成员时重复计算,为何会这样还搞不清楚。另外,有些成对出现的中文标点符号也可能会导致词组的判断与我们通常的算法不一致。以下代码尝试对这两种情形进行一定程度的规避,也许还存在问题,请测试效果:
  1. Sub ChineseCharCounting()
  2.     '统计汉字的字词频,并按降序排序
  3.     '中文词语的判断与Word的词典关联
  4.     Dim a As Byte
  5.     Dim n As Long
  6.     Dim TF As Boolean
  7.     Dim filetext As String
  8.     Dim d
  9.     Dim Wd As Range
  10.     Dim W As Range
  11.     Dim b
  12.     Dim e As Long
  13.     Dim c() As String
  14.     Dim i As Long
  15.     Dim temp As String
  16.     Dim st As Single
  17.    
  18.     a = MsgBox("词频统计请按“是”,字频统计请按“否”", vbYesNo, "中文字词频统计")
  19.     st = Timer
  20.     Application.ScreenUpdating = False
  21.     n = ActiveDocument.Content.ComputeStatistics(wdStatisticFarEastCharacters)
  22.     If ActiveDocument.Content.Text Like "*[【】〖〗《》〈〉〔〕]*" Then TF = True
  23.     With ActiveDocument.Content.Find
  24.         .Text = "[【】〖〗《》〈〉〔〕]"
  25.         .MatchWildcards = True
  26.         .Execute Replace:=wdReplaceAll
  27.     End With
  28.     Set d = CreateObject("Scripting.Dictionary")
  29.     If a = vbYes Then
  30.         For Each Wd In ActiveDocument.Words
  31.             With Wd
  32.                 If .Start < e Then .Start = e
  33.                 e = .End
  34.                 If .Text Like "*[一-龥]*" And Len(.Text) > 1 Then
  35.                     If .Text Like "*[!一-龥]*" = False And .Words.Count = 1 Then
  36.                         d(.Text) = d(.Text) + 1
  37.                     Else
  38.                         For i = 1 To Len(.Text)
  39.                             If Mid(.Text, i, 1) Like "[!一-龥]" Then Exit For
  40.                         Next
  41.                         With .Duplicate
  42.                             .End = .Start + i - 1
  43.                             For Each W In .Words
  44.                                 With W
  45.                                     If Len(.Text) > 1 Then
  46.                                         If Right(.Text, 1) Like "[!一-龥]" Then .End = .End - 1
  47.                                         If .Text Like "*[!一-龥]*" = False Then d(.Text) = d(.Text) + 1
  48.                                     End If
  49.                                 End With
  50.                             Next
  51.                         End With
  52.                     End If
  53.                 End If
  54.             End With
  55.         Next
  56.     Else
  57.         filetext = ActiveDocument.Content.Text
  58.         For i = 1 To Len(filetext)
  59.             temp = Mid(filetext, i, 1)
  60.             If temp Like "[一-龥]" Then d(temp) = d(temp) + 1
  61.         Next
  62.     End If
  63.     b = d.keys
  64.     ReDim c(UBound(b))
  65.     For i = 0 To UBound(b)
  66.         c(i) = b(i) & vbTab & d(b(i))
  67.     Next
  68.     If TF = True Then ActiveDocument.Undo 1
  69.    
  70.     With Documents.Add.Content
  71.         .Text = "文档共有" & n & "个中文字符。共提取到" & d.Count _
  72.             & IIf(a = 6, "个中文词语", "个不同的汉字") & ",其出现次数分别为:" & vbCrLf & Join(c, vbCrLf)
  73.         .Parent.DefaultTabStop = .Characters.First.Font.Size * 6
  74.         .MoveStart wdParagraph
  75.         .Sort , 2, wdSortFieldNumeric, wdSortOrderDescending, 1, , , , , , wdSortSeparateByTabs
  76.     End With
  77.     MsgBox "提取完毕。用时" & Format(Timer - st, "0") & "秒。"
  78.     Application.ScreenUpdating = True
  79. End Sub
复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-28 12:56 , Processed in 0.032736 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表