2014-01-23 55 views
0

背景:在“列中的”在工作表中“工作表Sheet”的每个小区的双循环

第一子检查的格式,通过在片材通过每个小区准备的相同列(模板),如果没有发现类似的情况,则调用子例程FlagError以将错误存储在工作表&中(现在部分允许我每秒创建一个新的错误工作表,但不会重复)工作表。

问题:

  • 一个错误说,片材超出范围和突出线 片( “模板”)激活:解决:缺失 “” .Thanks simoco用于指向那个。

  • 我想摆脱所有的goto语句,但我的有限的技术知识是好..限制我,可以有人请帮我修改代码。

的东西:

Global sheetname As String 

Sub errorsinsight_plus() 
    sheetname = "errorsheet" & Format(Now, "yyyy_mm_dd ss_nn_hh") 
    Dim i As Long, r As Range, j As Long 
    Dim ucolumn As String 
    Dim counter As Integer: counter = 1 

Sheets.Add.Name = sheetname 

    Sheets("sheet1").Activate 

' if your data is in a different column then change A to some other letter(s) 
    ucolumn = "A" 'sample number 

    'finds error in sample code 


For i = 2 To Range(ucolumn & Rows.Count).End(xlUp).Row 
     Set r = Range(ucolumn & i) 
Dim samplenof As Range 
Sheets("template").Activate 
For j = 1 To Range(ucolumn & Rows.Count) 
Set samplenof = Range(ucolumn & j) 
    Sheets("Sheet1").Activate 
    If Len(r) = 14 Then 
    Dim xcheck1 As Boolean 
    xcheck1 = r Like samplenof 
     If xcheck1 = True Then 
     GoTo nexti1 
     Else 
     GoTo nextj1 
     End If 
    ElseIf Len(r) = 15 Then 
    Dim xcheck2 As Boolean 
    xcheck2 = r Like samplenof 
     If xcheck2 = True Then 
     GoTo nexti1 
     Else 
     GoTo nextj1 
     End If 
    FlagErrors ucolumn, i, r, counter 
    Else: FlagErrors ucolumn, i, r, counter 
    End If 
nextj1: 
    Next j 
nexti1: 
Next i 

end sub 

Public Sub FlagErrors(ucolumn As String, i As Long, r As Range, ByRef counter As Integer) 
    Sheets(sheetname).Activate 
    Dim xerror As Range, yerror As Range 
    Range("A" & counter) = ucolumn & i 
    Range("B" & counter) = r 
    Sheets("sheet1").Activate 
    counter = counter + 1 
End Sub 
+0

如果'template'是一个表名(而不是VBA变量),你需要使用'表(“模板”)。Activate'代替'表(模板).Activate' –

+0

感谢,现在它工作正常。 – Solaire

回答

0

这个答案的第一个版本追捧这是前两个的意见给予澄清。

变化1

我已经在上面添加Option Explicit。这会导致编译器坚持声明所有变量。没有它,语句如Count = Conut + 1隐含声明Conut。这种错误可能是一场噩梦。

变化2

当你回来这个例程12个月,你会立刻知道什么ijcounter是谁?您需要一个命名变量的系统,以便您(或同事)在忘记后可以轻松地说出其目的。你可能不喜欢我的命名系统。好吧,选一个你喜欢的人。

Your name My name 
    i  RowSheet1Crnt 
    j  RowTemplateCrnt 
counter RowErrorCrnt 

更改3

您有:

Set r = Range(ucolumn & i) 
If Len(r) = 14 Then 

r是一个范围。范围的默认属性是Value。所以Len(r)相当于Len(r.Value)。但是,当我看到Len(r)我必须知道r是一个单元格范围来阐述这种说法。我避免假设任何对象的默认属性。对于范围,我总是包含.Value,因为我相信它使代码更具可读性。

但是,您只能使用r来获取该值。我删除了r并用一个字符串变量替换它。我不知道Range(ucolumn & i)是什么,所以我不能给它一个有意义的名字。我选择了CellValueSheet1Test,但您应该替换此名称。

所以我有以下但对于其他的变化:

CellValueSheet1Test = Range(ucolumn & RowSheet1Crnt).Value 
If Len(CellValueSheet1Test) = 14 Then 

变化4

您使用Range(ucolumn & RowSheet1Crnt).Value。我已经使用Cells(RowSheet1Crnt, ucolumn)Range没有错,但我发现Cells更灵活。第二个参数可以是列标识符,例如“A”或列号,例如1.当您跨多列操作时,这非常方便。

变化5

您切换使用激活工作表。即使您包含Application.ScreenUpdating = False,每次切换时都会有一定量的屏幕重新绘制。如果可能的话,这是一个声明。考虑:

CellValueSheet1Test = Cells(RowSheet1Crnt, ucolumn).Value 

With Worksheets("Sheet1") 
    CellValueSheet1Test = .Cells(RowSheet1Crnt, ucolumn).Value 
End With 

第一条语句对活动工作表进行操作。在第二组中,Cells之前的点意味着它可以在With声明中指定的工作表上进行操作。我不必切换到工作表来访问其内容。

With可以嵌套:

With Worksheets("Sheet1") 
    With .Cells(RowSheet1Crnt, ucolumn) 
    .Value = "X" 
    .Font.Bold = True 
    .Font.Color = RGB(0, 255, 255) 
    End With 
End With 

变化6

如果我做了很多与特定的工作,我会使用With Worksheets声明。您一次只能访问一个单元格,并且通过引用访问工作表的速度更快。

我:

Dim WshtSheet1 As Worksheet 
Dim WshtTemplate As Worksheet 

Set WshtSheet1 = Worksheets("Sheet1") 
Set WshtTemplate = Worksheets("template") 

CellValueSheet1Test = WshtSheet1.Cells(RowSheet1Crnt, ucolumn).Value 

我觉得这肯定是访问工作表 “工作表Sheet1” 的最佳途径。我对工作表“模板”使用了相同的技术,但有些人可能会认为With会更好。 Excel VBA的一个难题是,通常有几种方法可以达到相同的效果,并且最好使用哪种方式并不总是显而易见的。我发现每个程序员都有自己的最爱 - 你正在看我的。麻烦的是,当你看着不同程序员的工作时,每个人都会有自己的最爱。即使你不喜欢它们,你也必须意识到每种技术,因为其他人使用它们。

更改7

您有:

If Len(r) = 14 Then 
    Dim xcheck1 As Boolean 
    xcheck1 = r Like samplenof 
    If xcheck1 = True Then 
    GoTo nexti1 
    Else 
    GoTo nextj1 
    End If 
ElseIf Len(r) = 15 Then 
    Dim xcheck2 As Boolean 
    xcheck2 = r Like samplenof 
    If xcheck2 = True Then 
     GoTo nexti1 
    Else 
    GoTo nextj1 
    End If 

我看不到代码之间的差额为长度14和15,所以我已经合并即可。我看不出有什么优势,在使用xcheck1xcheck2如此,但对于其他的变化,这一切都变成了:

If Len(r) = 14 Or Len(r) = 15 Then 
    If r Like samplenof Then 
    GoTo nexti1 
    Else 
    GoTo nextj1 
    End If 

更改8

GoTo S码块引起了我最困难的尝试了解你想达到的目标。

在我看来,如果来自工作表“Sheet1”的值的长度不是14或15,这是一个错误;没有必要检查工作表“模板”。所以这个测试可以在内部循环之外进行。如果来自工作表“Sheet1”的值不是Like工作表“模板”中的任何值,我认为您需要报告一个错误。你有一个电话FlagErrors就在Else的上方,但我看不到它可以被执行。我完成了对这个街区的重新编码,但我无法确定我是否已经达到了你想要的效果。

非变化

您使用:

FlagErrors ucolumn, RowSheet1Crnt, CellValueSheet1Test, RowErrorCrnt 

我喜欢:

Call FlagErrors(ucolumn, RowSheet1Crnt, CellValueSheet1Test, RowErrorCrnt) 

我的选择可能是更多地与我所知道的其他编程语言。我不知道任何其他允许使用的格式的语言。但是,我不知道你的格式有缺点,所以我已经离开了它。

修改后的代码

我有测试此代码的手段。我已经解释了每一个变化,如果它不能如你所愿,你应该能够找出原因。祝你好运。

Option Explicit 
Global sheetname As String 

Sub errorsinsight_plus() 

    Application.ScreenUpdating = False 

    sheetname = "errorsheet" & Format(Now, "yyyy_mm_dd ss_nn_hh") 

    Dim ucolumn As String 

    Dim CellValueSheet1Test As String 
    Dim CellValueTemplateTest As String 
    Dim MatchFound As Boolean 
    Dim RowErrorCrnt As Long 
    Dim RowSheet1Crnt As Long 
    Dim RowSheet1Last As Long 
    Dim RowTemplateCrnt As Long 
    Dim RowTemplateLast As Long 
    Dim WshtSheet1 As Worksheet 
    Dim WshtTemplate As Worksheet 

    Set WshtSheet1 = Worksheets("Sheet1") 
    Set WshtTemplate = Worksheets("template") 

    Sheets.Add.Name = sheetname 

    ' if your data is in a different column then change A to some other letter(s) 
    ucolumn = "A" 'sample number 

    RowSheet1Last = WshtSheet1.Cells(Rows.Count, ucolumn).End(xlUp).Row 
    RowTemplateLast = WshtTemplate.Cells(Rows.Count, ucolumn).End(xlUp).Row 
    RowErrorCrnt = 1 

    'finds error in sample code 
    For RowSheet1Crnt = 2 To RowSheet1Last 
     CellValueSheet1Test = WshtSheet1.Cells(RowSheet1Crnt, ucolumn).Value 
     If Len(CellValueSheet1Test) = 14 Or _ 
     Len(CellValueSheet1Test) = 15 Then 
     MatchFound = False 
     For RowTemplateCrnt = 2 To RowTemplateLast 
      CellValueTemplateTest = WshtTemplate.Cells(RowTemplateCrnt, ucolumn).Value 
      If CellValueSheet1Test Like CellValueTemplateTest Then 
      MatchFound = True 
      Exit For 
      End If 
     Next 
     Else 
     ' Length of test value is neither 14 or 15. 
     FlagErrors ucolumn, RowSheet1Crnt, CellValueSheet1Test, RowErrorCrnt 
     End If 
     If Not MatchFound Then 
     FlagErrors ucolumn, RowSheet1Crnt, CellValueSheet1Test, RowErrorCrnt 
     End If 
    Next RowSheet1Crnt 

End Sub 
Public Sub FlagErrors(ByVal ucolumn As String, ByVal RowSheet1 As Long, _ 
         ByVal CellValueSheet1 As String, ByRef RowError As Long) 

    With Sheets(sheetname) 
    .Cells(RowError, "A").Value = ucolumn & RowSheet1 
    .Cells(RowError, "B").Value = CellValueSheet1 
    RowError = RowError + 1 
    End With 

End Sub 
+0

谢谢Tony,这些肯定应该是你的建议。 – Solaire

+0

ucolumnf应该被替换为samplenof – Solaire

+0

我想没有人会得到我的乱码我会把它标记为已解决,感谢您的帮助 – Solaire