Office中国论坛/Access中国论坛

标题: Office PK 第五期,Excel挑战Access:算个数(单条件计数) [打印本页]

作者: pureshadow    时间: 2016-3-26 18:03
标题: Office PK 第五期,Excel挑战Access:算个数(单条件计数)
在Excel的单元格里写公式,这是Excel的强项,为了不让Access感到心理崩溃,我也不想弄个类似于要求计算100以内质数之类的BT题,就写个简单的公式吧。
话说我不小心把自己迷失在过往已经中了,请帮忙找一下,这里一共有多少个自己。
计数就行,不必在表上高亮显示。





作者: tmtony    时间: 2016-3-26 21:46
不光崩溃,而且泪奔
作者: pureshadow    时间: 2016-3-27 09:31
王站你不用这样吧,你出的第二期里,就用到类似功能的,有贴为证:Excel和AccessPK第二期:Access自定义单号http://www.office-cn.net/thread-121535-1-1.html

我当时不会写这块的代码,就用了个被VBA高手鄙视的法子:用代码调用工作表函数,写成application.countif...
这会你跳出来说你崩溃泪奔?谁信啊?!
作者: roych    时间: 2016-3-27 14:59
单行或者单列很简单。单列的话,dcount应该没问题。单行使用记录集,move到目标行计算即可。

这个题目难就难在于countif的自由性(任意区域,甚至多区域),为了尽量匹配到,需要用到VBA,这里先假定是任意连续区域(多区域条件暂不考虑):
  1. Function Countif(ByVal strWhere As String, _
  2.             ByVal lngSColumn As Long, _
  3.             ByVal lngEColumn As Long, _
  4.             ByVal lngSRow As Long, _
  5.             ByVal lngERow As Long) As Long
  6.             
  7.     Dim rst As New ADODB.Recordset
  8.     Dim i As Long, j As Long, lngCount As Long
  9.    
  10.    
  11.    
  12.     rst.Open "tbl_Countif", CurrentProject.Connection, adOpenKeyset, adLockOptimistic
  13.    
  14.     '初始化,以免出错。数字格式部分暂由数据有效性处理,这里略去。
  15.     lngCount = 0
  16.     If lngSColumn < 1 Then lngEColumn = 1
  17.     If lngEColumn > rst.Fields.count Then lngEColumn = rst.Fields.count
  18.     If lngSRow < 1 Then lngEColumn = 1
  19.     If lngERow > rst.RecordCount Then lngERow = rst.RecordCount

  20.     For i = lngSRow To lngERow
  21.         For j = lngSColumn - 1 To lngEColumn - 1
  22.             If rst(j) Like "*" & strWhere & "*" Then
  23.                 lngCount = lngCount + 1
  24.             End If
  25.         Next
  26.         rst.MoveNext
  27.     Next
  28. Countif = lngCount
  29. End Function
复制代码

暂不做窗体,有兴趣的版友可以尝试做下。建议使用组合框来设置数据的有效性。这个例子支持通配符,例如:
Countif("可*", 1, 7, 1, 2)=1
Countif("可", 1, 7, 1, 2)=0
其它说明【不可能或较困难的任务】:
大家可以先参考下,算是抛砖引玉吧。
另外,本例如果用记录集的getrows可能会有更高的效率,不过也更加繁琐(所以没测试)。具体思路大约是:

作者: zhuyiwen    时间: 2016-3-27 19:50
妖,变态,眼睛吃不消,我数了好久。
作者: pureshadow    时间: 2016-3-27 21:17
zhuyiwen 发表于 2016-3-27 19:50
妖,变态,眼睛吃不消,我数了好久。

谁让你用肉眼数了?
作者: tmtony    时间: 2016-3-28 10:03
pureshadow 发表于 2016-3-27 21:17
谁让你用肉眼数了?

哈哈
作者: tmtony    时间: 2016-3-28 12:00
roych 发表于 2016-3-27 14:59
单行或者单列很简单。单列的话,dcount应该没问题。单行使用记录集,move到目标行计算即可。

这个题目难 ...

这个函数不错,长access志气,灭Excel威风。
作者: pureshadow    时间: 2016-3-28 15:54
tmtony 发表于 2016-3-28 12:00
这个函数不错,长access志气,灭Excel威风。

你以为Excel里没有Dcount?[attach]58566[/attach]

作者: zhuyiwen    时间: 2016-3-28 17:05
pureshadow 发表于 2016-3-27 21:17
谁让你用肉眼数了?

本来就是肉眼凡胎
作者: 纸鸽    时间: 2016-3-29 11:41
本帖最后由 纸鸽 于 2016-3-29 18:13 编辑
roych 发表于 2016-3-27 14:59
单行或者单列很简单。单列的话,dcount应该没问题。单行使用记录集,move到目标行计算即可。

这个题目难 ...

我们不用countif  我们用sum((a1:h11="已")*1)
作者: pureshadow    时间: 2016-4-4 15:21
这个问题归根到底,如果有用Countif或者Dcount这样的函数的话,就是脱不了循环的法子,我这样理解对不对?
作者: roych    时间: 2016-4-4 22:07
pureshadow 发表于 2016-4-4 15:21
这个问题归根到底,如果有用Countif或者Dcount这样的函数的话,就是脱不了循环的法子,我这样理解对不对?

固定列的话,Dcount没问题(多个Dcount相加即可)。不过域函数(D字头)的效率较低,数据较多的时候,还是用ADO会方便些,或者用Count聚合函数(不过这时候就需要写where条件子句了)。
不定列的话,则基本只能使用ADO循环了。
作者: pureshadow    时间: 2016-4-4 22:22
貌似Excel里正好相反,DCount效率相对高,ADO倒不见得高效到哪里去。只不过要用VBA调用工作表函数,总是被鄙视
作者: 纸鸽    时间: 2016-4-8 18:51
pureshadow 发表于 2016-4-4 22:22
貌似Excel里正好相反,DCount效率相对高,ADO倒不见得高效到哪里去。只不过要用VBA调用工作表函数,总是被 ...

application.if(会被鄙视,谁爱鄙视谁鄙视,来一起application.***)




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3