简体   繁体   English

Excel和VBA在宏途中崩溃

[英]Excel and VBA Crashing Midway Through Macro

I am new to VBA and hoping for some help implementing a user-defined function. 我是VBA的新手,希望对实现用户定义的功能有所帮助。 I would really appreciate any help! 我将非常感谢您的帮助!

Context : I am trying to import a batch of fixed-width text files into separate Excel workbooks. 上下文 :我正在尝试将一批固定宽度的文本文件导入单独的Excel工作簿中。 The text files all have the same fields and format. 文本文件都具有相同的字段和格式。 I know the length of each field. 我知道每个字段的长度。 Currently, I am trying to get my VBA code to work for a single text file. 目前,我正在尝试使我的VBA代码可用于单个文本文件。

Issue : As I'm new to VBA, I looked for existing code. 问题 :由于我是VBA的新手,所以我在寻找现有的代码。 I found Chip Pearson's ImportFixedWidth function , edited one error found by another StackOverflow user , and have been trying to implement my TestImport function (see below) ever since. 我找到了Chip Pearson的ImportFixedWidthWidth函数编辑了另一个StackOverflow用户发现的一个错误此后一直在尝试实现我的TestImport函数(请参见下文)。 (*Note that the ... is just for the sake of brevity - not actually included in the code.) (*请注意,...只是为了简洁起见,实际上并未包含在代码中。)

Sub TestImport()
Dim L As Long
L = ImportFixedWidth("/Users/gitanjali/Desktop/CAC06075test.txt", _
    Range("A1"), _
    False, _
    vbNullString, _ 
    "1,5|2,45|3,3|4,45|5,45|6,45|7,60|8,15|9,11|10,60| _
                 11,60|12,10|13,5|14,5|15,3|16,3|17,3|18,3|19,11|20,10| 
                 ...190,250|191,250")
End Sub

See the ImportFixedWidth function at the end of this post. 请参阅本文结尾处的ImportFixedWidth函数。

I then tried to run the macro within the workbook, but it crashes VBA and Excel every time. 然后,我尝试在工作簿中运行宏,但是每次都会使VBA和Excel崩溃。 The first field is imported (not the other 190) into the open workbook, but the program stops responding and has to be quit. 第一个字段(不是其他190个字段)被导入到打开的工作簿中,但是程序停止响应,必须退出。

Debugging : The code compiles. 调试 :代码编译。 I don't get any errors when I step through either the TestImport or ImportFixedWidth code. 通过TestImport或ImportFixedWidth代码时,我没有任何错误。 I've tried running the macro on both a Mac and a Windows PC (it crashes on both). 我尝试在Mac和Windows PC上都运行宏(两者均崩溃)。 And the first field is imported properly before the program crashes, so I'm not sure what the problem is. 而且第一个字段在程序崩溃之前已正确导入,因此我不确定是什么问题。

Question : I'm at a loss for next steps in terms of debugging. 问题 :在调试方面,我不知所措。 Are there any obvious errors in my implementation? 我的实施过程中是否存在任何明显的错误? What would my next logical debugging step be? 我的下一个逻辑调试步骤是什么?

Function ImportFixedWidth(FileName As String, _
    StartCell As Range, _
    IgnoreBlankLines As Boolean, _
    SkipLinesBeginningWith As String, _
    ByVal FieldSpecs As String) As Long
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ImportFixedWidth
' By Chip Pearson, chip@cpearson.com www.cpearson.com
' Date: 27-August-2011
' Compatible with 64-bit platforms.
'
' This function imports text from a fixed field width file.
' FileName is the name of the file to import. StartCell is
' the cell in which the import is to begin. IgnoreBlankLines
' indicates what to do with empty lines in the text file. If
' IgnoreBlankLines is False, an empty row will appear in the
' worksheet. If IgnoreBlankLines is True, no empty row will
' appear in the worksheet. SkipLinesBeginingWith indicates
' what character, if any, at the begining of the line indicates
' that the line should not be imported, such as fpr providing for
' comments within the text file. FieldSpecs indicates how to
' map the data into cells. It is a string of the format:
'           start,length|start,length|start,length...
' where each 'start' is the character position of the field
' in the text line and each 'length' is the length of the field.
' For example, if FieldSpecs is
'           1,8|9,3|12,5
' indicates the first field starting in position 1 for a
' length of 8, the second field starts in position 9 for a
' length of 3, and finally a field beginning in position 12
' for a length of 5. Fields can be in any order and may
' overlap.
' You can specify a number format for the field which will
' be applied to the worksheet cell. This format should not
' be in quotes and should follow the length element. For example,
'       2,8|9,3,@|12,8,dddd dd-mmm-yyyy
' This specifies that no formatting will be applied to column 2,
' the Text (literal) format will be applied to column 9, and
' the format 'dddd dd-mmm-yyyy' will be applied to column 12.
'
' The function calls ImportThisLine, which should return
' True to import the text from the file, or False to skip
' the current line.
' This function returns the number of records imported if
' successful or -1 if an error occurred.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim FINdx As Long
Dim C As Long
Dim R As Range
Dim FNum As Integer
Dim S As String
Dim RecCount As Long
Dim FieldInfos() As String
Dim FInfo() As String
Dim N As Long
Dim T As String
Dim B As Boolean

Application.EnableCancelKey = xlInterrupt
On Error GoTo EndOfFunction:

If Dir(FileName, vbNormal) = vbNullString Then
    ' file not found
    ImportFixedWidth = -1
    Exit Function
End If

If Len(FieldSpecs) < 3 Then
    ' invalid FieldSpecs
    ImportFixedWidth = -1
    Exit Function
End If

If StartCell Is Nothing Then
    ImportFixedWidth = -1
    Exit Function
End If

Set R = StartCell(1, 1)
C = R.Column
FNum = FreeFile

Open FileName For Input Access Read As #FNum
' get rid of any spaces
FieldSpecs = Replace(FieldSpecs, Space(1), vbNullString)
' omit double pipes ||
N = InStr(1, FieldSpecs, "||", vbBinaryCompare)
Do Until N = 0
    FieldSpecs = Replace(FieldSpecs, "||", "|")
    N = InStr(1, FieldSpecs, "||", vbBinaryCompare)
Loop
' omit double commas
N = InStr(1, FieldSpecs, ",,", vbBinaryCompare)
Do Until N = 0
    FieldSpecs = Replace(FieldSpecs, ",,", ",")
    N = InStr(1, FieldSpecs, ",,", vbBinaryCompare)
Loop

' get rid of leading and trailing | characters, if necessary
If StrComp(Left(FieldSpecs, 1), "|", vbBinaryCompare) = 0 Then
    FieldSpecs = Mid(FieldSpecs, 2)
End If
If StrComp(Right(FieldSpecs, 1), "|", vbBinaryCompare) = 0 Then
    FieldSpecs = Left(FieldSpecs, Len(FieldSpecs) - 1)
End If

Do
    ' read the file
    Line Input #FNum, S
    If SkipLinesBeginningWith <> vbNullString And _
            StrComp(Left(Trim(S), Len(SkipLinesBeginningWith)), _
            SkipLinesBeginningWith, vbTextCompare) Then
        If Len(S) = 0 Then
            If IgnoreBlankLines = False Then
                Set R = R(2, 1)
            Else
                ' do nothing
            End If
        Else
            ' allow code to change the FieldSpecs values

            If FieldSpecs = vbNullString Then
                ' FieldSpecs is empty. Do nothing, don't import.
            Else
                If ImportThisLine(S) = True Then
                    FieldInfos = Split(FieldSpecs, "|")
                    C = R.Column
                    For FINdx = LBound(FieldInfos) To UBound(FieldInfos)
                        FInfo = Split(FieldInfos(FINdx), ",")
                        R.EntireRow.Cells(1, C).Value = Mid(S, CLng(FInfo(0)), CLng(FInfo(1)))
                        C = C + 1
                    Next FINdx
                    RecCount = RecCount + 1
                End If
                Set R = R(2, 1)
            End If
        End If
    Else
        ' no skip first char
    End If

Loop Until EOF(FNum)

EndOfFunction:
If Err.Number = 0 Then
    ImportFixedWidth = RecCount
Else
    ImportFixedWidth = -1
End If
Close #FNum
End Function

Private Function ImportThisLine(S As String) As Boolean

Dim N As Long
Dim NoImportWords As Variant
Dim T As String
Dim L As Long

NoImportWords = Array("page", "product", "xyz")
For N = LBound(NoImportWords) To UBound(NoImportWords)
    T = NoImportWords(N)
    L = Len(T)
    If StrComp(Left(S, L), T, vbTextCompare) = 0 Then
        ImportThisLine = False
        Exit Function
    End If
Next N
ImportThisLine = True
End Function

it is your "field definition string" "1,5|2,45|3,3|4,45|5,45|6,45|7,60|8,15|9,11|10,60| _ ... the first digit of each pair is the starting position and the second is the length ... so it should be "1,5|6,45|51,3|54,45|99,45|144,45|189,60|249,15|264,11|275,60| _ 它是您的“字段定义字符串” "1,5|2,45|3,3|4,45|5,45|6,45|7,60|8,15|9,11|10,60| _ ...每对的第一个数字是起始位置,第二个数字是长度...,因此应为"1,5|6,45|51,3|54,45|99,45|144,45|189,60|249,15|264,11|275,60| _ "1,5|6,45|51,3|54,45|99,45|144,45|189,60|249,15|264,11|275,60| _ i have not checked those values, but it is close 1+5=6+45=51+3=54+45=99 ..... "1,5|6,45|51,3|54,45|99,45|144,45|189,60|249,15|264,11|275,60| _我尚未检查这些值,但接近1 + 5 = 6 + 45 = 51 + 3 = 54 + 45 = 99 .....

In Terms of Debugging the next step I would use is to try and work out where the code is crashing out. 在调试条款的下一步我会用就是尝试找出其中代码崩溃了。 I usually write my On Error Statements so I can turn error trapping on and off ie 我通常会写我的On Error Statements,这样我就可以打开和关闭错误陷阱,即

instead of 代替

 On Error GoTo EndOfFunction:

use 采用

 If InDebugMode then On Error Goto EndOfFunction:

InDebugMode is just InDebugMode只是

 Public Const InDebugMode = True

That way the code will halt when something goes wrong and you can then use watches etc to then figure out what is happening (see http://www.cpearson.com/excel/DebuggingVBA.aspx ) 这样,当出现问题时,代码将停止,然后您可以使用手表等来找出正在发生的情况(请参阅http://www.cpearson.com/excel/DebuggingVBA.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM