Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 2861|回复: 8

公式能解决的,代码有什么好的方法?

[复制链接]
发表于 2014-12-6 09:55 | 显示全部楼层 |阅读模式
在函数版看到一问题
http://www.excelpx.com/thread-335629-1-1.html

尝试用代码解决一下,考虑用字典,还要借助辅助单元格两次排序,然后连接字符串
感觉比较麻烦,请大家讨论一下,用代码有什么好的办法?

新建 Microsoft Excel 工作表 (2).zip

1.88 KB, 下载次数: 34

excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
 楼主| 发表于 2014-12-6 16:31 | 显示全部楼层
写一段代码抛砖引玉,不相信公式能够解决的,代码会如此繁复
Sub Macro1()
Dim arr, d, i&, j%, zf$, z$
Set d = CreateObject("scripting.dictionary")
arr = Range("a1").CurrentRegion
For i = 2 To UBound(arr)
    zf = arr(i, 1)
    For j = 1 To Len(zf)
        z = Mid(zf, j, 1)
        d(z) = d(z) + 1
    Next
    Range("e1").Resize(1, d.Count) = d.keys
    Range("e2").Resize(1, d.Count) = d.items
    Range("e1").CurrentRegion.Sort Key1:=[e2], Order1:=xlDescending, Key2:=[e1], _
    Order2:=xlAscending, Header:=xlGuess, Orientation:=xlLeftToRight
    w = Range("e1").Resize(1, d.Count)
    arr(i, 2) = Join(Application.Index(w, 1, 0), "")
    Range("e1").CurrentRegion = ""
    d.RemoveAll
Next
Range("b1").Resize(UBound(arr)) = Application.Index(arr, 0, 2)
End Sub
回复

使用道具 举报

 楼主| 发表于 2014-12-6 19:33 | 显示全部楼层
不借助单元格排序,有没有简单的方法可以实现要求?
回复

使用道具 举报

 楼主| 发表于 2015-2-26 08:33 | 显示全部楼层
  1. Sub Macro1()
  2. Dim arr, d, i&, j%, k%
  3. Set d = CreateObject("scripting.dictionary")
  4. arr = [a2:a5]
  5. For i = 1 To UBound(arr)
  6.     zf = arr(i, 1)
  7.     For j = 1 To Len(zf)
  8.         z = Val(Mid(zf, j, 1))
  9.         d(z) = d(z) + 1
  10.     Next
  11.     zd = Application.Max(d.items)
  12.     zx = Application.Min(d.items)
  13.     p = ""
  14.     For j = zd To zx Step -1
  15.         For k = 0 To 9
  16.             If d(k) = j Then p = p & k
  17.         Next
  18.     Next
  19.     MsgBox p
  20.     arr(i, 1) = p
  21.     d.RemoveAll
  22. Next
  23. Range("e2").Resize(UBound(arr)) = arr
  24. End Sub
复制代码
回复

使用道具 举报

发表于 2015-2-26 10:20 | 显示全部楼层
借用4楼思路,不用字典:
  1. Sub Macro1()
  2.     Dim arr, i&, j%, k%
  3.     arr = [a2:a5]
  4.     For i = 1 To UBound(arr)
  5.         zf = arr(i, 1)
  6.         For j = Len(zf) To 1 Step -1
  7.             For k = 0 To 9
  8.                 If Len(zf) - Len(Replace(zf, k, "")) = j Then p = p & k
  9.             Next
  10.         Next
  11.         arr(i, 1) = p: p = ""
  12.     Next
  13.     Range("e2").Resize(UBound(arr)) = arr
  14. End Sub
复制代码

评分

参与人数 1 +18 收起 理由
dsmch + 18

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2015-2-26 11:12 | 显示全部楼层
  1. Sub Macro1()
  2. Dim arr, w(9), i&, j%, k%
  3. arr = [a2:a5]
  4. For i = 1 To UBound(arr)
  5.     zf = arr(i, 1)
  6.     For j = 1 To Len(zf)
  7.         z = Val(Mid(zf, j, 1))
  8.         w(z) = w(z) + 1
  9.     Next
  10.     p = ""
  11.     For j = Len(zf) To 1 Step -1
  12.         For k = 0 To 9
  13.             If w(k) = j Then p = p & k
  14.         Next
  15.     Next
  16.     arr(i, 1) = p
  17.     Erase w
  18. Next
  19. Range("e2").Resize(UBound(arr)) = arr
  20. End Sub
复制代码
回复

使用道具 举报

发表于 2015-2-26 13:54 | 显示全部楼层
点评:

一、在本楼题目这样纯数字计算时,2楼、4楼使用字典的代码就没有意义了。

二、5楼算法有重大意义,但反复使用Replace处理效率非常低。

三、6楼代码使用数组记录大大改进了计算效率。
但尚有改进余地……最后的提取结果有很大的冗余计算量,需要计算字符长度*10(遍历0-9)


四、代码改进如下:
  1. Sub test5()
  2.     Dim arr, a&(9), i&, j&, k&, n&, s$, t$
  3.     arr = Range("a1").CurrentRegion
  4.     For i = 2 To UBound(arr)
  5.         s = arr(i, 1)
  6.         n = Len(s)
  7.         For j = 1 To n
  8.             t = Mid(s, j, 1)
  9.             a(t) = a(t) + 1
  10.         Next
  11.         s = ""
  12.         k = 0
  13.         Do
  14.             k = k + 1
  15.             For j = 9 To 0 Step -1
  16.                 If a(j) = k Then s = j & s: n = n - a(j): If n = 0 Then Exit Do
  17.             Next
  18.         Loop
  19.         arr(i, 1) = "'" & s '此处需加单引号、保证首位0能被显示。
  20.         Erase a
  21.     Next
  22.     Range("d1").Resize(UBound(arr)) = arr
  23. End Sub
复制代码
但实际上,此代码和6楼代码比速度的差异也很有限。……呵呵,只能说是一种可以借鉴的思路。
或许在别处的类似问题的处理上,速度的差异就会有意义了。

评分

参与人数 1 +18 收起 理由
dsmch + 18

查看全部评分

回复

使用道具 举报

发表于 2016-9-1 23:54 | 显示全部楼层
本帖最后由 pengyx 于 2016-9-2 14:07 编辑

试写一个:每个字符串整理只需看   字符串长度*2+10次即可
Sub test6()
Dim arr, w(9),  i&, j%, k%
arr = [a2:a5]
For i = 1 To UBound(arr)
    zf = arr(i, 1)
    Redim x(1 to Len(zf))
     t = ""
    For j = 1 To Len(zf)
        z = Val(Mid(zf, j, 1))
        w(z) = w(z) + 1
    Next
    For k = 1 To 10
        If w(k - 1) <> "" Then
            a = w(k - 1)
            x(a) = x(a) & k - 1
        End If
    Next
    For l = Len(zf) To 1 Step -1
        If x(l) <> "" Then
            t = t & x(l)
        End If
    Next
arr(i, 1) = "'" & t
Erase w
Next
[e2].Resize(UBound(arr)) = arr
End Sub

评分

参与人数 1 +18 收起 理由
dsmch + 18

查看全部评分

回复

使用道具 举报

发表于 2017-6-2 15:35 | 显示全部楼层
OK各位大师谢谢啦
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-25 17:28 , Processed in 0.548384 second(s), 17 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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