楼主 wcymiss |
Q:如图,如何对产品名称里的规格提取出来并统计其出现的次数? A:函数对于12mm和2mm在一起的时候,或是规格的前导字符不统一的时候,处理非常麻烦。用vba正则做比较方便。代码如下:- Sub cs()
- Dim arr, i&, brr(), j&, mt, a
- arr = Range("a2:a" & Cells(Rows.Count, 1).End(3).Row) '产品名称读入数组
- ReDim brr(0 To UBound(arr), 1 To 1) '定义数组,用于提取材料名
- ReDim crr(0 To UBound(arr), 1 To 1) '定义数组,用于统计各材料出现次数
- brr(0, 1) = "材料1" '表头字段
- crr(0, 1) = "材料1出现次数" '表头字段
- With CreateObject("vbscript.regexp") '正则对象
- .Global = True
- For i = 1 To UBound(arr) '循环
- j = 0 '初始化j值,j值用于表示材料有几种
- .Pattern = "(^|\D)(\d+mm)(?!.*\D\2)" '提取材料名的正则表达式
- For Each mt In .Execute(arr(i, 1)) '处理每个匹配的字符串
- j = j + 1 '每匹配到一个,j值就加1,表示材料种类的增加
- If UBound(brr, 2) < j Then '对材料名数组和材料次数数组进行增容
- ReDim Preserve brr(0 To UBound(arr), 1 To j)
- ReDim Preserve crr(0 To UBound(arr), 1 To j)
- brr(0, j) = "材料" & j
- crr(0, j) = "材料" & j & "出现次数"
- End If
- brr(i, j) = mt.SubMatches(1) '提取材料名
- .Pattern = "(^|\D)" & brr(i, j) '匹配提取到的材料名
- Set a = .Execute(arr(i, 1)) '匹配到的个数就是该材料出现的次数
- crr(i, j) = a.Count
- Next
- Next
- End With
- Range("b1", Cells(Rows.Count, Columns.Count)).ClearContents '清除要写入数据的区域
- Range("b1").Resize(UBound(brr) + 1, UBound(brr, 2)) = brr '写入材料名
- Range("b1").Offset(0, UBound(brr, 2)).Resize(UBound(crr) + 1, UBound(crr, 2)) = crr '写入各材料出现的次数
- End Sub
正则提取名称.rar
正则表达式(^|\D)(\d+mm)(?!.*\D\2) 解析: 1、 (^|\D)为第一组,意为:或为字符串的开头,或为1个非数字 2、(\d+mm)为第二组,意为:1个或多个数字与字符“mm”的合并字符串。 3、(?!.*\D\2) ,为负向零宽断言,限定表达式所匹配的第二组,必须在其最后的字符串没有重复。 以"11mm白玻钢化+湿法(透明)+1mm白玻钢化+11mm白玻钢化"为例: (^|\D)(\d+mm)分别有开头的"11mm"、"+1mm"、"+11mm"可被匹配到,其中第二组的内容为:"11mm"、"1mm"、"11mm"。由于表达式后面有零宽断言对第二组进行了去重,"11mm"在后面有重复,不符合要求,所以最后被此表达式匹配的字符串为:"+1mm"和"+11mm",其中第二组内容为:"1mm"和"11mm“。
小贴士:在按F8逐行运行代码,同时打开”视图-本地窗口“可以查看到正则表达式匹配的字符串。
参考资料:http://deerchao.net/tutorials/regex/regex.htm |