是否可以找到每个excel行的最后一个元素距离?

时间:2013-01-01 12:40:27

标签: excel-vba vbscript ado dao adodb

考虑以下矩阵:

    Col1    Col2    Col3    Col4    Col5    Col6    Col7
R1   x       x                        x
R2           x                x              x
R3                                                    x
R4           x        x       x
R5                                    x

现在使用VBScript或ADO,哪一个可以找到每行最后一个元素的距离? 距离的定义 距离只不过是最后一个元素放在给定矩阵中的单元格数。例如说 -

  • Dist(R1)= 5

  • Dist(R4)= 4同样明智

我尝试了以下内容:

Option Explicit

Dim ArrayListTaskDetails : Set ArrayListTaskDetails = CreateObject("System.Collections.ArrayList")
Dim i,colcount

i=2
Do while i < = objExcel1.Application.WorksheetFunction.CountA(ob.Rows(1))

colcount=objExcel1.Application.WorksheetFunction.CountA(ob.Rows(i))
ArrayListTaskDetails.Add(colcount)

i=i+1
Loop

ArrayListTaskDetails.Sort()
i=ArrayListTaskDetails.Count
MsgBox("HighestColumnNumner:" & ArrayListTaskDetails(i-1))

但它没有用,因为无法处理空白之间。

Thnaks,

2 个答案:

答案 0 :(得分:2)

给定与.xls的ADODB连接,

"SELECT * FROM [Sheet2$]"

显示

PID     T1      T2      T3      T4      T5
11      1       <Null>  1       1       <Null>
14      1       1       1       <Null>  1
21      <Null>  <Null>  1       <Null>  <Null>
88      1       1       1       <Null>  <Null>
99      1       <Null>  <Null>  <Null>  <Null>
100     <Null>  <Null>  <Null>  <Null>  <Null>
101     1       1       1       1       1

嵌套的IIF(IsNull(Col),[...],ColNum),如

"SELECT PID, IIF(IsNull(T5),IIF(IsNull(T4),IIF(IsNull(T3),IIF(IsNull(T2),IIF(IsNull(T1),0,1),2),3),4),5) As RMCol FROM [Sheet2$]"

将导致

PID     RMCol
11      4
14      5
21      3
88      3
99      1
100     0
101     5

尝试解释:

如果IIF(BoolExpression, TrueValue, FalseValue)为True,TrueValue表达式的评估结果为BoolExpression,否则为FalseValue;因此,在IIF的True槽中放置另一个IsNull(Colx)将连续测试列,直到非空列将触发返回FalseValue(列号)。

是的:SQL是一个处理任意行数(固定/精心设计的列集)的工具;因此,如果您设计错误,将一组逻辑上不受限制的信息放入列中 - 而不是(另一个)表 - 这就是您支付的价格。

<强>更新

我毫不犹豫地提出这个问题,因为从长远来看,所有的黑客和快捷方式都会失败 - 而且你必须从一开始就以一个不错的设计开始,但是:

递归函数:

Function genIFF(n)
  If 1 = n Then
     genIFF = "IIF(IsNull(T1),0,1)"
  Else
     genIFF = "IIF(IsNull(T" & n & ")," & genIFF(n - 1) & "," & n & ")"
  End If
End Function

很乐意创造:

  Dim n
  For n = 1 To 5
      WScript.Echo n, genIFF(n)
  Next

1 IIF(IsNull(T1),0,1)
2 IIF(IsNull(T2),IIF(IsNull(T1),0,1),2)
3 IIF(IsNull(T3),IIF(IsNull(T2),IIF(IsNull(T1),0,1),2),3)
4 IIF(IsNull(T4),IIF(IsNull(T3),IIF(IsNull(T2),IIF(IsNull(T1),0,1),2),3),4)
5 IIF(IsNull(T5),IIF(IsNull(T4),IIF(IsNull(T3),IIF(IsNull(T2),IIF(IsNull(T1),0,1),2),3),4),5)

甚至:

50 IIF(IsNull(T50),IIF(IsNull(T49),IIF(IsNull(T48),IIF(IsNull(T47),IIF(IsNull(T46),IIF(IsNull(T45),IIF(IsNull(
T44),IIF(IsNull(T43),IIF(IsNull(T42),IIF(IsNull(T41),IIF(IsNull(T40),IIF(IsNull(T39),IIF(IsNull(T38),IIF(IsNul
l(T37),IIF(IsNull(T36),IIF(IsNull(T35),IIF(IsNull(T34),IIF(IsNull(T33),IIF(IsNull(T32),IIF(IsNull(T31),IIF(IsN
ull(T30),IIF(IsNull(T29),IIF(IsNull(T28),IIF(IsNull(T27),IIF(IsNull(T26),IIF(IsNull(T25),IIF(IsNull(T24),IIF(I
sNull(T23),IIF(IsNull(T22),IIF(IsNull(T21),IIF(IsNull(T20),IIF(IsNull(T19),IIF(IsNull(T18),IIF(IsNull(T17),IIF
(IsNull(T16),IIF(IsNull(T15),IIF(IsNull(T14),IIF(IsNull(T13),IIF(IsNull(T12),IIF(IsNull(T11),IIF(IsNull(T10),I
IF(IsNull(T9),IIF(IsNull(T8),IIF(IsNull(T7),IIF(IsNull(T6),IIF(IsNull(T5),IIF(IsNull(T4),IIF(IsNull(T3),IIF(Is
Null(T2),IIF(IsNull(T1),0,1),2),3),4),5),6),7),8),9),10),11),12),13),14),15),16),17),18),19),20),21),22),23),2
4),25),26),27),28),29),30),31),32),33),34),35),36),37),38),39),40),41),42),43),44),45),46),47),48),49),50)

视觉证据阅读和测试将从嵌入式IIF中扼杀Excel,这仍然是对受虐狂的练习。

答案 1 :(得分:2)

另一种方法......在VBSCRIPT中使用公式

Dim oXLApp, oXLWb, oXLWs

Set oXLApp = CreateObject("Excel.Application")

'~~> Show Excel
oXLApp.Visible = True

'~~> Open files (Change as applicable)
Set oXLWb = oXLApp.Workbooks.Open("C:\MyFile.xlsx")
Set oXLWs = oXLWb.Sheets(1)

Dim lRow, i, tmp

With oXLWs
    lRow = .Range("A" & .Rows.Count).End(-4162).Row

    For i = 2 To lRow
        tmp = oXLApp.Evaluate("=ADDRESS(ROW(A" & i & "),MATCH(INDEX($" & i _
        & ":$" & i & ",MAX(IF($A" & i & ":$K" & i & "<>"""",COLUMN($A" & i _
        & ":$K" & i & ")))),A" & i & ":K" & i & "),1)")

        MsgBox .Range("A" & i).Value & " :- " & .Range(tmp).Column - 1
    Next
End With

<强>截图

enter image description here

<强>跟进

根据要求

Dim oXLApp, oXLWb, oXLWs

Set oXLApp = CreateObject("Excel.Application")

'~~> Hide Excel
oXLApp.Visible = True

'~~> Open files
Set oXLWb = oXLApp.Workbooks.Open("C:\MyFile.xlsx")
Set oXLWs = oXLWb.Sheets(1)

Dim lRow, i, tmp, MyArray, ColNo, ReturnName

With oXLWs
    lRow = .Range("A" & .Rows.Count).End(-4162).Row

    ColNo = .Columns.Count

    ReturnName = Split(.Cells(, ColNo).Address, "$", -1,1)(1)

    For i = 2 To lRow
        tmp = oXLApp.Evaluate("=ADDRESS(ROW(A" & i & "),MATCH(INDEX($" & i _
        & ":$" & i & ",MAX(IF($A" & i & ":$" & ReturnName & i & _
        "<>"""",COLUMN($A" & i & ":$" & ReturnName & i & ")))),A" & _
        i & ":" & ReturnName & i & "),1)")

        msgbox .Range("A" & i).Value & " :- " & .Range(tmp).Column - 1
    Next
End With

更多关注

Option Explicit

Dim oXLApp, oXLWb, oXLWs
Dim lRow, i, tmp, MyArray, ColNo, ReturnName

Set oXLApp = CreateObject("Excel.Application")

'~~> Hide Excel
oXLApp.Visible = True

'~~> Open files
Set oXLWb = oXLApp.Workbooks.Open("C:\MyFile.xlsx")

'~~> Set the Sheet 1 as sheet1
Set oXLWs = oXLWb.Sheets(1)

With oXLWs
    '~~> Get the last row in the worksheet
    lRow = .Cells.Find("*", .Range("A1"), -4123, 2, 1, 2).Row

    '~~> Get the total col count
    ColNo = .Columns.Count

    '~~> This will return the column name from column number
    ReturnName = Split(.Cells(, ColNo).Address, "$", -1, 1)(1)

    For i = 1 To lRow
        '~~> We are using the Evaluate to calculate the formula
        '~~> which will find our result
        tmp = oXLApp.Evaluate("=ADDRESS(ROW(A" & i & "),MATCH(INDEX($" & i _
        & ":$" & i & ",MAX(IF($A" & i & ":$" & ReturnName & i & _
        "<>"""",COLUMN($A" & i & ":$" & ReturnName & i & ")))),A" & _
        i & ":" & ReturnName & i & "),1)")

        '~~> This will return the column number
        MsgBox "Last Col in Row " & i & " is " & .Range(tmp).Column
    Next
End With