2

考虑以下矩阵:

    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 是否可以找到每行最后一个元素的距离?距离距离的定义只不过是最后一个元素放置在给定矩阵中的单元格数。例如说 -

  • 距离(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))

但它不起作用,因为无法处理空白之间的问题。

纳克斯,

4

2 回答 2

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)表达式的计算结果为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)

对 n Excel 将在嵌套 IIF 上窒息的内容进行视觉校对和测试留作自虐狂的练习。

于 2013-01-01T13:07:12.470 回答
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

截屏

在此处输入图像描述

跟进

根据要求

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
于 2013-01-01T14:24:26.303 回答