楼主 chenlifeng |
我通过亲身遇到的问题,并把它解决了,现在总结如下: 问题: 输入一个表示地名的几个字,如“湖南”、“湖南省”、“山东聊城”、“山东 聊城1”、“13广东 大良镇”等(前后可有干扰字符),如何在地址库中找到与之最符合的一个或几个详细地址?(相当于百度功能来查找地址) 如刚才举例的几个关键词语的答案依次为:“湖南省”、“湖南省”、“山东省聊城市”、“广东省佛山市顺德区大良街道办事处”,总之,关键证词词语包括到了哪一个行政级别,地址答案就到那一级别,不往下把更详细的显示。
答案: 附件1(名称:关键字中排干扰,地址库里显英豪):已经成功调试,是最快、最新能排干扰的查找方式。 在窗体输入口中输入想要查询的内容,点击“查找”,即可在一秒内找到最合适的答案(关键词语越详细越快,当只有一个字时,由于要产生的答案太多,速度较慢;而输入地名中的连续两个字,速度快到只用半秒就见答案);
附件2(名称:只排除后面干扰、速度时快时慢):成功调试,速度时快时慢,当输入地址表中靠上面的行中的地址时,速度快,越靠下面的行、越靠后面的列,速度越慢。原因是它查找的方式是以行为单位查找匹配的, 而附件1是以列为查找依据、且分5个行政区,故最多只查找5列,速度自然跟上了。有关这两者的代码,见后; 附件3(名称:不紧不慢):不排除干扰,有干扰即为打不到答案。查找时,每次总是用时三秒;但思路非常有意思,代码简短,乃一朋友所作。
下面第一段代码为附件1中的部分代码,是与附件2唯一不同的地方,用的是列的方法查找,速度最快:- For Each 字典2元素 In 字典2
- For I = 1 To UBound(Arr)
- If InStr(字典2元素, Arr(I, 1)) > 0 Then
- 字典2元素变体 = Replace(字典2元素, Arr(I, 1), "")
- If Len(字典2元素变体) = 0 Then If Not 字典3.Exists(Arr(I, 1)) Then 字典3.Add Arr(I, 1), "": Exit For '即答案只是省名罢了
- K = 重复值所在的最大行数(Range("a" & I & ":a" & Range("A65536").End(xlUp).Row), Range("a" & I).Value)
- For J = I To K
- If InStr(字典2元素变体, Arr(J, 2)) > 0 Then
- If Mid(Replace(字典2元素变体, Arr(J, 2), ""), 1, 4) = "塔城地区" Then
- J = 2899: L = 2905: 字典2元素变体 = Replace(字典2元素变体, Arr(J, 2), ""): 字典2元素变体 = Replace(字典2元素变体, "塔城地区", ""): GoTo line3
- ElseIf Mid(Replace(字典2元素变体, Arr(J, 2), ""), 1, 5) = "阿勒泰地区" Then
- J = 2906: L = 2912: 字典2元素变体 = Replace(字典2元素变体, Arr(J, 2), ""): 字典2元素变体 = Replace(字典2元素变体, "阿勒泰地区", ""): GoTo line3
- End If
- 字典2元素变体 = Replace(字典2元素变体, Arr(J, 2), "")
-
- If Len(字典2元素变体) = 0 Then If Not 字典3.Exists(Arr(I, 1) & Arr(J, 2)) Then 字典3.Add Arr(I, 1) & Arr(J, 2), "": Exit For '即答案只是省和市名罢了
- L = 重复值所在的最大行数(Range("b" & I & ":b" & K), Range("b" & J).Value)
- line3:
- For M = J To L
- If InStr(字典2元素变体, Arr(M, 3)) > 0 Then
- 字典2元素变体 = Replace(字典2元素变体, Arr(M, 3), "")
- If Len(字典2元素变体) = 0 Then If Not 字典3.Exists(Arr(I, 1) & Arr(J, 2) & Arr(M, 3)) Then 字典3.Add Arr(I, 1) & Arr(J, 2) & Arr(M, 3), "": Exit For '即答案只是省、市、乡名罢了
- N = 重复值所在的最大行数(Range("C" & J & ":C" & L), Range("C" & M).Value)
- For O = 4 To Range("D" & N).End(xlToRight).Column
- If InStr(字典2元素变体, Arr(N, O)) > 0 Then
- If Not 字典3.Exists(Arr(I, 1) & Arr(J, 2) & Arr(M, 3) & Arr(N, O)) Then 字典3.Add Arr(I, 1) & Arr(J, 2) & Arr(M, 3) & Arr(N, O), "": Exit For '即答案已是省、市、乡、镇了
- ElseIf InStr(Arr(N, O), 字典2元素变体) > 0 Then
- If Not 字典3.Exists(Arr(I, 1) & Arr(J, 2) & Arr(M, 3) & Arr(N, O)) Then 字典3.Add Arr(I, 1) & Arr(J, 2) & Arr(M, 3) & Arr(N, O), "": Exit For '即答案已是省、市、乡、镇了
- End If
- Next
- Exit For
- ElseIf InStr(Arr(M, 3), 字典2元素变体) > 0 Then
- If Not 字典3.Exists(Arr(I, 1) & Arr(J, 2) & Arr(M, 3)) Then 字典3.Add Arr(I, 1) & Arr(J, 2) & Arr(M, 3), "": Exit For '即答案只是省、市、乡名罢了
- End If
- Next
- Exit For
- ElseIf InStr(Arr(J, 2), 字典2元素变体) > 0 Then
- If Not 字典3.Exists(Arr(I, 1) & Arr(J, 2)) Then 字典3.Add Arr(I, 1) & Arr(J, 2), "": Exit For '即答案只是省和市名罢了
- End If
- Next
- Exit For
- ElseIf InStr(Arr(I, 1), 字典2元素) > 0 Then
- If Not 字典3.Exists(Arr(I, 1)) Then 字典3.Add Arr(I, 1), "": Exit For '即答案只是省名罢了
- End If
- Next
- Next
附件2中的部份代码,与附件一的作用是一样的,但速度较慢:- zzz = 0 '初始化zzz,zzz有其妙用处
- fo = 2 '初始华fo,它与ZZZ一样代表源地址库中的行数。
- line4: '标志4
- For Each abc In di 'di 就是所输入的TEXTBOX1中的内容,进行了整理后的内容,每个字符中间用星号隔开。可能会循环一次或多次
- cde = "*"
- For bcd = 1 To Len(abc)
- cde = cde & Mid(abc, bcd, 1) & "*"
- Next
-
- For ufo = fo To Sheets("全国地址库").Range("A65536").End(xlUp).Row
- For ee = 1 To Sheets("全国地址库").Range("A" & ufo).End(xlToRight).Column
- If Not dic.Exists(Arr(ufo, ee)) Then
- dic.Add Arr(ufo, ee), "" 'dic 是源数据 ,现在被定义为字典,向里面写数据,这一句是把每行的数据收集起来,再到下面做判断,故每一行有多少就收集多少到字典中。
- ppp = Join(dic.KEYS, "")
- If ppp Like cde Then '把上面收集来的数据与输入的内容比较判断,一旦符合就退出这个UFO循环, 进入下一个环节(给地址查找行政划分的单位)否则清空字典,再从上面来过。
- GoTo line3
- Else:
- If ee > 3 Then dic.Remove Arr(ufo, ee) 'dic.RemoveAll
- End If
- End If
- Next
- dic.RemoveAll
- zzz = zzz + 1 '这里的累加,是为了后面作准备:万一下面这句是属于误判,则根据ZZZ再返回到刚才收集数据的下一行进行,而不必再从头再来,以致死循环。至于下句会出现误判的原因:如输入“蓬安”,四川省有个蓬安县,但就在这个答案的上一行有两个县(各占一单元格),一个叫太蓬乡,另个是固安乡,两者合一起就饱含了刚才的“蓬安”两字,符合下面的要求,但最后会导致答案为空。
- Next
-
- '*******下面意思是,给上面查找到的结果,赋上正确的行政划分地址,有行政地址的则免********
- line3:
- u = abc 'abc即前面 进行了重复排查后的字典di中的元素,也是手动输入后整理出来的结果
- For Each gg In dic
- If InStr(u, gg) > 0 Then '源数据中的行政地址与 U(或abc) 中的作一一对比,如果源数据的某一个数据被包括在U中,则
- u = Replace(u, gg, "") '发现两者存在重复,清除U中的内容,
- dic.Remove gg '亦清除字典dic中的重复内容
- If Len(u) = 0 Then '这里是指全部把dic中的内容匹配完了,结果为空,说明输入的内容正好是一个完整的行政划分。
- If Not ddc.Exists(abc) Then ddc.Add abc, "" '向新字典ddc 中写abc,这里表示所输入部分正好是一个完整的行政划分
- End If
- End If
- Next
- If Len(u) > 0 Then '没有清除完的abc内容
- For Each gg In dic
- If InStr(gg, u) > 0 Then '输入数据u与剩余的源数据gg作一一对比,与上面的一一对比正好相反 '如果存在重复,则:
- x = Mid(gg, InStr(gg, u) + Len(u), Len(gg) - InStr(gg, u) + Len(u) - 1) '提取源数据GG中比输入数据多余的部分
- y = abc & x '再把多余的这部分与已经从最先输入的TEXTBOX1内容得了的答案di合并
- If Not ddc.Exists(y) Then ddc.Add y, "" 'ddc 向新字典中写入 “所输入的TEXTBOX1内容加 所缺少内容”
- Exit For '找到后,给上述字典赋值完后,退出本轮的循环,进行新一个ABC的循环,如果字典DI有多个元素的话。
- End If
- Next
- End If
- Next
- If zzz = Sheets("全国地址库").Range("A65536").End(xlUp).Row Then MsgBox "没找到": Exit Sub:
- If UBound(ddc.KEYS) + 1 = 0 Then: fo = fo + zzz: GoTo line4 '这里的确UBound(ddc.keys) + 1 = 0表示数字是空?!
- If UBound(ddc.KEYS) = 0 And Right(CC, 1) = "市" Then
- For Each gg In ddc
- If InStr(gg, Mid(CC, 1, Len(CC) - 1)) = 0 Then CC = Mid(CC, 1, Len(CC) - 1): xh = 1: ddc.RemoveAll: GoTo line0 '本行作用在于:把不是“市”的行政单位当成“市”时,去掉“市”再运行一次。如“新化县”存在,“新化市”不存在。
- Next
- End If
附件三的代码部分,思路不一样:- For i = 2 To UBound(brr)
- If brr(i) <> "" Then
- lng = InStr(brr(i), .TextBox1) + Len(.TextBox1) - 1
- If Right(Left(brr(i), lng), Len(.TextBox1)) = .TextBox1 Then
- d(Left(brr(i), lng)) = ""
- End If
- Else
- Exit For
- End If
- Next
不紧不慢.rar 只排除后面干扰、速度时快时慢.rar 关键字中排干扰,地址库里显英豪.rar |