ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > E文精选 > Excel VBA > 一个字典与正则结合的实例。

一个字典与正则结合的实例。

作者:绿色风 分类: 时间:2022-08-17 浏览:201
楼主
liuguansky
问题的提出:

 

数量/箱来计算每件或每箱的数量,同时来对原版中的内容进行分配。
分配规则如下:
类似这样的表达方式1-R28L748(36):前面是代码,后面()中的是数量。
先分配前面的,再依次向后进行分配,同一编号用同一原版进行处理。
比如1.2.231.80100编号:第一个记录是288/4=72
那么应该分配前面的两个36/36,结果应该返回为:
1-R28L748(36)  1-R28L749(36)
第二条记录,就拉着分配:
1-R28L750(72)
这样依次下去。
如果一箱的数量小于一个代码的数量,则需把代码进行拆分返回。


问题的分析:
1.对于特殊形式的字符串处理,我们可以很容易的考虑到正则表达式,同时结合分组来进行数据的提取。
2.在为同一编号,运用同一原版,故可以想到用字典来进行编号的惟一性识别。
3.因为同一编号是对同一原版进行数量的判断处理,故可以设置数组进行相应的数量元素的减少或消失[设置为空文本]
因为字典的ITEM项目操作多种 元素会比较烦琐,故直接引用数组入ITEM项目。
4.对每条记录的实际数量,与字典ITEM数组中的数量元素进行比较判断来进行字符串返回即可。

问题的实现:
  1. Sub justtest()
  2.     Dim arr, i&, arrt() As String, K&, d, j%, StrTemp$, arrk, ark '定义变量
  3.     arr = Range("a2:d" & Cells(Rows.Count, 1).End(3).Row).Value '获取待处理数据区域入数组
  4.     Set d = CreateObject("scripting.dictionary") '创建字典项目
  5.     ReDim arrt(1 To UBound(arr, 1), 1 To 1) '重定义结果数组
  6.     With CreateObject("vbscript.regexp") '创建正则项目
  7. '知识点1:正则对字符串的处理
  8.         .Global = True '全局为真
  9.         .Pattern = "(\d-R\d{2}L\d{3})\((\d+)\)" '匹配代码段与数量段,进行分组$1$2
  10. '知识点2:分组便于分段截获项目
  11.         For i = 1 To UBound(arr, 1) '循环数据源数组
  12.             If Not d.exists(arr(i, 1)) Then '如果字典项目不存在的话
  13.                 If .test(arr(i, 3)) Then '如果原版匹配有正则段
  14.                     ark = Split(.Replace(Replace(arr(i, 3), " ", ""), "@$1@$2"), "@") '生成代码段与数量段间隔数组
  15. '知识点3:正则.replace方法的分组替换,配合SPLIT返回结果数组
  16.                 End If
  17.                 d.Add arr(i, 1), ark '同时创建项目,设置ITEM项为数组,方便后续处理
  18. '知识点4:依处理需求,添加数组入字典ITEM项目
  19.             End If
  20.             K = arr(i, 2) / arr(i, 4) '返回每箱装数量
  21.             arrk = d(arr(i, 1)) '获取相应编码对应的字典ITEM项入数组,方便后续取值判断
  22.             StrTemp = "" '初始化返回代码+数量字符串
  23. '知识点5:标识字符串或标识位的初始化,防止前期结果对后期标识的影响
  24.             For j = 1 To UBound(arrk) Step 2 '循环原版处理后的字符串,因代码段与数量段相隔,故STEP2
  25.                 If arrk(j) <> "" Then '对非空元素 进行判断处理
  26.                     If K >= CLng(arrk(j + 1)) Then '如果待生成数量不小于元素数量
  27.                         StrTemp = StrTemp & "  " & arrk(j) & "(" & CLng(arrk(j + 1)) & ")" '则返回对应代码+数量
  28.                         K = K - CLng(arrk(j + 1)): arrk(j) = "": arrk(j + 1) = "" '同时对K进行减少,清空对应的数组元素
  29.                         If K = 0 Then Exit For '如果刚好处理完,则跳出循环
  30. '知识点6:循环达到目的即跳出循环,避免无用或多余的循环判断
  31.                         Else '如果待生成数量小于元素数量
  32.                         StrTemp = StrTemp & " " & arrk(j) & "(" & K & ")" '生成对应代码+待生成数量
  33.                         arrk(j + 1) = CLng(arrk(j + 1)) - K '处理对应元素的数量
  34.                         Exit For '同时进行循环跳出
  35.                     End If
  36.                 End If
  37.             Next j
  38.             d(arr(i, 1)) = arrk '更新字典对应项目的ITEM项
  39. '知识点7:字典ITEM项目的独立性[只依附于对应的KEY],需重新赋值回去
  40.             arrt(i, 1) = Mid(StrTemp, 3) '返回字符串
  41. '知识点8:字符串连接后,直接以MID来去除第一个连接多余间隔符。
  42.         Next i
  43.         Range("e:e").ClearContents '清空返回数据区域
  44.         Range("e2").Resize(i - 1, 1) = arrt '返回结果
  45.     End With
  46.     Set d = Nothing '清空变量
  47. End Sub
知识点分析:
1.正则用于处理字符串上有很大的优势,通过分析数据的通性,来书写PATTERN进行目标字符的匹配,可以很方便的辅以我们来进行后续的其他操作。
2.匹配后,当我们要抽取其中的部分匹配结果可以用()加以分组,分组后有两种方式返回:
第一种就是通过每一个匹配结果的submatches集合进行调用。
第二种就是本例中的结合replace来进行处理。
每一个分组在REPLACE中的匹配结果用$1/2/3...这样编号下去。
本例中把代码与数量分组,进行特殊字符的间隔REPLACE后再SPLIT返回为数组,是一种常用的取分组匹配结果入数组的方式。
3.关于字典的ITEM,它是个大肚能容天下物的东西,数组、字典、对象都可以放进去。
所以有时我们可以根据我们处理的数据结果,对其进行不同的赋值。
需要注意的是ITEM为数组、字典、对象等的时候,要把它赋值时的变量名与其本身区分开来。
ITEM是个依附于对应KEY值而存在的,不能单独去获取其值,所以只能字典进行返回,所以进行ITEM的处理时,应先赋值给对象/变量,操作完后再赋值回字典的ITEM项目
4.有时我们在数组的循环中,会设定很多标识位/参照值等等的中间变量 ,这些变量我们要分清哪些是在全过程累加,哪些是只在单一循环中累加,这个时候我们要进行合理的分析并进行清空与初始化。
5.循环过程中,如果达到某些条件后,我们应该进行跳出循环处理 ,防止循环的继续运行,发生多余或不必要的循环。

写在最后:
此例是一个字典+正则+数组的结合实例,对我们综合处理问题很有帮助。其中涉及的几个小技巧与知识点很实用,希望以上分析对大家有帮助,若对上述实例中的知识点或代码有疑问或更好的建议,请跟帖或短消息我。


桌面.rar



该帖已经同步到
2楼
tldrtnnhtg
谢谢老师分享 学习到很多知识 见识到正则的强大
3楼
wqfzqgk

4楼
冰心8549
谢谢分享,学习学习
5楼
JOYARK1958
好东西 我下载来好好学习
6楼
老糊涂
学习正则

免责声明

有感于原ExcelTip.Net留存知识的价值及部分知识具有的时间限定性因素, 经与ExcelTip.Net站长Apolloh商议并征得其同意, 现将原属ExcelTip.Net的知识帖采集资料于本站点进行展示, 供有需要的人士查询使用,也慰缅曾经的论坛时代。 所示各个帖子的原作者如对版权有异议, 可与本人沟通提出,或于本站点留言,我们会尽快处理。 在此,感谢ExcelTip.Net站长Apolloh的支持,感谢本站点所有人**绿色风(QQ:79664738)**的支持与奉献,特此鸣谢!
------本人网名**KevinChengCW(QQ:1210618015)**原ExcelTip.Net总版主之一

评论列表
sitemap