【问题标题】:How do you make an Excel spreadsheet range store a VBA variable?如何让 Excel 电子表格范围存储 VBA 变量?
【发布时间】:2015-09-28 14:26:31
【问题描述】:

好吧,所以我已经花了.. 我只想说.. 像一个小时(遗憾的是我在撒谎,这就像整整一周)试图弄清楚这一点。 而且我想不通godd*mnit >_

假设我们在记事本 (_A_File_.txt) 中有一个仅包含 4 行的文本文件:

ACCOUNT NUMBER: 123456789    '(line 2)
SHORT NAME: JON SMITH        '(line 2)
ACCOUNT NUMBER: 987654321    '(line 3)
SHORT NAME: BOB BARKER       '(line 4)

让我们假设在一个 excel 电子表格中:

Range C1 = "actNumberTrim"
Range C2 = "shortNameTrim"
Range C3 = "actNumberTrim"
Range C4 = "shortNameTrim"

让我们也假设下面的 VBA 脚本:

Sub obey_me_you_stoopit_code_()

Dim actNumber As Integer
Dim shortName As Integer
Dim actNumberTrim As String
Dim shortNameTrim As String
Dim trimArray1 As Variant
Dim myFile As String
Dim text As String
Dim textline As String


actNumber = InStr(text, "ACCOUNT NUMBER: ") 'THERE IS A SPACE BETWEEN : AND "
shortName = InStr(text, "SHORT NAME: ") 'THERE IS A SPACE BETWEEN : AND "
actNumberTrim = Mid(text, actNumber + 16, 10)
shortNameTrim = Mid(text, shortName + 12, 10)


myFile = "C:\Users\Bob\Desktop\_A_File_.txt"

Open myFile For Input As #1
Do Until EOF(1)

    Line Input #1, textline
    text = text & textline
    Loop

trimArray1 = ThisWorkbook.Worksheets("sheet1").Range("C1:C4")


For i = 1 To UBound(trimArray1)

 MsgBox trimArray1(i, 1)

Next i
Close #1
End Sub

我得到的输出是:

[ actNumberTrim ]
[ shortNameTrim ]
[ actNumberTrim ]
[ shortNameTrim ]

我将如何解决上述问题,以便 Ranges C1:C4 中的值被视为:

  1. 变量而不是,比如说.. 单元格中无意义的文本
  2. 所以返回的输出是:

    [ 123456789 ]
    [ JON SMITH ]
    [ 987654321 ]
    [ BOB BARKER ]
    

我尝试更改actNumberTrimshortNameTrim 的数据类型。 它没有用 我得到的只是这个:

运行时错误:“你的代码糟透了”

想法?

EDIT 1(尝试使用 Microsoft Scripting Runtime)

    Dim trimArray1 As Variant
    Dim myFile1 As String
    Dim text As String
    Dim textline As String
    Dim myDict As New Dictionary

    myFile1 = "C:\Users\BOB\Desktop\_A_File_.txt"
    Open myFile1 For Input As #1
    Do Until EOF(1)

        Line Input #1, textline
        text = text & textline
        Loop
    Close #1
    trimArray1 = ThisWorkbook.Worksheets("sheet22").Range("C1:C4")
    v = Split(textline, ":") 'where v has been declared to be variant
    myDict.Add Trim(v(0)), Trim(v(1))
    For i = 1 To UBound(trimArray1)

    MsgBox myDict(trimArray1(i, 1))

    Next i


    [ BLANK ]
    [ BOB BARKER ]
    [ BLANK ]
    [ BOB BARKER ]

包含的单元格 C1:C4:

    ACCOUNT NUMBER
    SHORT NAME
    ACCOUNT NUMBER
    SHORT NAME

不确定我做错了什么,或者我是否忽略了某些事情。我如何将这种方法用于没有“:”分隔它们的字段?我发布的文本文件版本有点过于简单化了。反馈?

编辑 2 以下是我原来的做法

以下是示例文本文件中两条完整记录的示例:

    ACCOUNT ABCDEF12                                                                 
    CUSTOMER NAME:    JOHN B. SMITH         CSA REP:  154983                   
    ACCOUNT OPEN:     05/10/15
    CUSTOMER ADDRESS: 123 SOMEWHERE DRIVE   SOMETHING HERE:                   
    LAST ORDER:       06/24/2011             COUNTRY CODE: UNITED STATES      
    INVOICE #:        123456789             STATE CODE:    CALIFORNIA         
    LAST MAINTENANCE: 01/02/15               COUNTY CODE:  UNCODED            
    SOME INDICATOR:   NO   COMPLAINTS: NO   IPM IND:       DATAPREP/PERF4     
    SOME INDICATOR:   NO STATUS:  NONE      AUTO RENEW:    YES                
    SOMETHING HERE   NO                             
    SOMETHING HERE:          ABC IND:       
    SOMETHING HERE   2    ABC ASSET NO:  T                                           

    ACCOUNT ABCDEF12                                                                 
    CUSTOMER NAME:    JOHN B. SMITH         CSA REP:  154983                   
    ACCOUNT OPEN:     05/10/15
    CUSTOMER ADDRESS: 123 SOMEWHERE DRIVE   SOMETHING HERE:                   
    LAST ORDER:       06/24/2011             COUNTRY CODE: UNITED STATES      
    INVOICE #:        123456789             STATE CODE:    CALIFORNIA         
    LAST MAINTENANCE: 01/02/15               COUNTY CODE:  UNCODED            
    SOME INDICATOR:   NO   COMPLAINTS: NO   IPM IND:       DATAPREP/PERF4     
    SOME INDICATOR:   NO STATUS:  NONE      AUTO RENEW:    YES                
    SOMETHING HERE:   NO                             
    SOMETHING HERE:          ABC IND:       
    SOMETHING HERE:   2    ABC ASSET NO:  T                                               

下面是我最初的编码方式:

'
    Dim myFile As String
    Dim text As String
    Dim textline As String
    Dim cstAct as integer
    Dim actOpe as integer
    Dim cusNam as integer
    Dim act as integer
    Dim reg as integer

    myFile = "put file patch to text file here"
    myFile = Application.GetOpenFilename()

    Do Until EOF(1)
    Line Input #1, textline
    text = text & textline
    Loop

    cusAct = InStr(text, "ACCOUNT ")
    actOpe = InStr(text, "ACCOUNT OPEN:")
    reg = InStr(text, "REGION:")
    cusNam = InStr(text, "CUSTOMER NAME:")

    For i = 2 To ThisWorkbook.Worksheets("b2").Range("a65536").End(xlUp).Row
    ThisWorkbook.Worksheets("name").Range("a" & i).Value = Mid(text, act + 6, 9)
    ThisWorkbook.Worksheets("name").Range("b" & i).Value = Mid(text, cstAct + 6, 9)
    ThisWorkbook.Worksheets("name").Range("c" & i).Value = Mid(text, actOpe + 13, 27)
    ThisWorkbook.Worksheets("name").Range("d" & i).Value = Mid(text, cusNam  + 20, 19)

    next i

    'Format and autofit                         
    For x = 2 To ThisWorkbook.Worksheets("b2").Range("a65536").End(xlUp).Row
    Range("a" & x).Value = Application.WorksheetFunction.Clean(trim(Range("a" & x)))
    Range("b" & x).Value = Application.WorksheetFunction.Clean(trim(Range("b" & x)))
    Range("c" & x).Value = Application.WorksheetFunction.Clean(trim(Range("c" & x)))
    'etc etc
    next x

【问题讨论】:

  • 您需要解释“将值视为变量”的含义。价值观很好,价值观,而不是变量。变量可以保存值。细胞也可以。 VBA 完全能够(基本上)将单元格视为变量。可以通过 Range("C1").Value = 不管将值分配给 C1(例如),您甚至可以声明设置为等于 C1 的范围变量。为什么这样的东西还不够好?你想完成什么?
  • 您正在拆分 textline,其中包含文件的最后一行。所以你的v 变量是:("SHORT NAME", "BOB BARKER")。然后您的myDict 有一个带有键"SHORT NAME" 和值"BOB PARKER" 的条目。因此,当您尝试访问键 "ACCOUNT NUMBER" 的值时,您什么也得不到。当您尝试访问"SHORT NAME" 的值时,您会得到"BOB PARKER"。您知道Watch Window 和VBA 拥有的其他调试工具吗?他们会让你免于很多挫折..
  • 顺便说一句,根据this,通过访问一个不存在的密钥,您实际上可以使用Empty 项目即时创建一个
  • 这个结构是静态的吗?即每个帐户的行数总是与您的样本中的两个相同吗?如果是这样,在“:”上拆分并根据需要进行操作将非常容易。让我知道,我将发布我的意思的示例。
  • 是的,行数始终相同。如果您有一个您认为可行的样本,我将不胜感激。

标签: string excel vba parsing substring


【解决方案1】:

您可以将字符串用作字典的(其行为类似于链接到相应的变量)。在工具/参考下的 VBA 编辑器中,包含对 Microsoft Scripting Runtime 的参考。然后在你的代码的顶部有一行像

Dim myDict As New Dictionary 

然后,当您遍历文件并通过连续的行加载变量 textline 时,不要将它附加到大变量的末尾,而是使用行

v = Split(textline, ":") 'where v has been declared to be variant
myDict.Add Trim(v(0)), Trim(v(1))

修复 C 列中的单元格,使它们与文本文件中冒号前的实际(修剪)字符串一致。无需消除空格 - "Account Number" 是一个完全有效的单元格值和一个完全有效的字典键。稍后,当您遍历从 C 列中提取的值时,替换

MsgBox trimArray1(i, 1)

MsgBox myDict(trimArray1(i, 1))

这应该(如果我正确理解你的意图)做你想做的事。

【讨论】:

  • 我尝试了您建议的方法并取得了部分成功。看来我做错了什么。我遗漏了什么吗?我将如何将此方法应用于在同一行上包含例如 ACCOUNT NUMBER 和 SHORT NAME 的行?对于没有像“:”这样的分隔符的字段怎么办?
  • 在您修改后的代码中,以v = Split(textline .... 开头的两行属于逐行读取文件的循环主体,而不是在循环之后(顺便说一句Loop 本身如果它的缩进与它的主体不同,那么终止该循环会更好看)。照原样 - 您只需将最后一行数据添加到字典中(正如 loannis 已经指出的那样)。如果您的文件具有某种逻辑顺序,那么它可以被解析,但我不知道如何解析,因为除了冒号分隔的数据示例之外,您没有给出任何内容,每行 2 个字段。
  • 我的错。我在原始代码中包含了上面文本文件的一个更好的示例。我的第一种方法效果很好。一切都被解析得很好。这不是我的代码进入文本文件中的下一条记录(或帐户记录),而是一遍又一遍地循环第一个记录。
  • 在这个阶段,你问的是一个完全不同的问题。编辑应该澄清一个问题,而不是把它们变成别的东西。大图是您可以设置一个字典,允许您访问文件中的各种数据。你仍然需要努力弄清楚如何加载字典,然后用它来解决你想要解决的任何问题。如果您在解析时遇到问题,请提出另一个问题。
猜你喜欢
  • 2018-03-29
  • 2023-03-19
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-13
  • 1970-01-01
相关资源
最近更新 更多