2016-04-15 57 views
2

我是VBA的超级新手。我正在处理一个循环和创建句子的问题,但是我遇到了溢出行的问题。你能解释我出错的地方吗?VBA修复溢出行

Sub clue() 
Dim name, room, weapon As String 
Dim can, dag, lead, rev, rop, wre, total, least As Double 
Dim row As Integer 


Cells(1, 1).Activate 
cam = 0 
dag = 0 
lead = 0 
rev = 0 
rop = 0 
wre = 0 
row = 1 

Do Until IsEmpty(ActiveCell) 

name = ActiveCell.Value 
room = ActiveCell.Offset(1, 0).Value 
weapon = ActiveCell.Offset(2, 0).Value 


Cells(row, 3).Value = name & " in the " & room & " with the " & weapon & "." 

If weapon = "Candlestick" Then 
    can = can + 1 
End If 
If weapon = "Dagger" Then 
    dag = dag + 1 
End If 
If weapon = "Lead Pipe" Then 
    lead = lead + 1 
End If 
If weapon = "Revolver" Then 
    rev = rev + 1 
End If 
If weapon = "Rope" Then 
    rop = rop + 1 
End If 
If weapon = "Wrench" Then 
    wre = wre + 1 
End If 
ActiveCell.End(xlDown).End(xlDown).Activate 
row = row + 1 
Loop 

total = can + dag + lead + rev + rop + wre 
Cells(2, 6) = can 
Cells(3, 6) = dag 
Cells(4, 6) = lead 
Cells(5, 6) = rev 
Cells(6, 6) = rop 
Cells(7, 6) = wre 

Cells(2, 7) = can/total 
Cells(3, 7) = dag/total 
Cells(4, 7) = lead/total 
Cells(5, 7) = rev/total 
Cells(6, 7) = rop/total 
Cells(7, 7) = wre/total 

least = 1000000000 
If can < least Then least = can 
If dag < can Then least = dag 
If lead < dag Then least = lead 
If rev < lead Then least = rev 
If rop < rev Then least = rop 
If wre < rop Then least = wre 

Cells(10, 5) = least 
End Sub 

我想打印出一个句子使用某些输入一排,但由于输入改变我想要打印的下一行(因此该行=行+ 1)的下句,但它使说有一个“溢出”的问题,我需要改变一些东西,但我不知道为什么。有人知道吗?

谢谢!

+0

定义行作为长数据类型'Dim row As Long'将解决它。 – newguy

+0

在模块的最顶端添加'Option Explicit' - 你已经声明'can'可以作为一个变体并且为'cam'设置一个值。 –

回答

0

你可能有一个溢出,一旦您已经阅读32K行

,它是因为你宣布你row变量integer

其更改为long,你将能够在20亿行工作

Dim row As Long 

试着记住这一点:

Byte  between 0 and 255. 
Integer  between -32,768 and 32,767. 
Long  between – 2,147,483,648 and 2,147,483,647. 
Currency between -922,337,203,685,477.5808 and 922,337,203’685,477.5807. 
Single  between -3.402823E38 and 3.402823E38. 
Double  between -1.79769313486232D308 and 1.79769313486232D308. 
0

返回Long,而不是一个Integer

请注意, Dim name, room, weapon As String
仅将weapon定义为string,其余为variant
正确的语法是
Dim name as string, room as string, weapon As String

0

我喜欢的“游戏”旨意问题,因为你宣布自己“超级新VBA”,我认为它可以帮助你的你的初始代码如下重构

Option Explicit 

Sub clue() 

Dim can As Long, dag As Long, lead As Long, rev As Long, rop As Long, wre As Long, row As Long 
Dim weapon As String 
Dim roomsRng As Range, areaRng As Range, roomsReportRng As Range, finalStatsRng As Range, leastStatsRng As Range ' these are useful range variable. you'll set them and use to avoid loosing control over what you're actually handling 

' here follows a section dedicated to setting relevant "ranges". this helps a lot in avoiding loosing control over what you're actually handling 
With ActiveSheet 'always explicitly qualify which worksheet do you want to work with. "ActiveSheet" is the currently active one, but you may want to qualify 'Worksheets("MySheetName")' 
    Set roomsRng = .Range("A1:A" & .cells(.Rows.Count, 1).End(xlUp).row) 'set roomsRng range as the one collecting activesheet cells in column "A" down to the last non empty one 
    Set roomsRng = roomsRng.SpecialCells(xlCellTypeConstants, xlTextValues) 'select only non blank cells of "roomsRng" range (skip blanks) 

    Set roomsReportRng = .cells(1, 3) ' set the range you start writing rooms report from 
    Set finalStatsRng = .Range("F2") ' set the range you'll start writing final stats from 
    Set leastStatsRng = .Range("E10") ' set the range you'll write the least found weapon number in 
End With 

For Each areaRng In roomsRng.Areas 'loop through all "Areas" of "roomsRng" range cells: an "Area" is a group of contiguous cells 
    Call WriteRoomsReport(areaRng.cells, roomsReportRng, row, weapon) 'write room report 
    Call UpdateWeaponsStats(weapon, can, dag, lead, rev, rop, wre) ' update weapons statistics 
Next areaRng 

Call WriteFinalStats(can, dag, lead, rev, rop, wre, finalStatsRng, leastStatsRng) ' write final statistics 

End Sub 



Sub WriteRoomsReport(roomCells As Range, reportCell As Range, row As Long, weapon As String) 
Dim arr As Variant 'it'll be used as an array, see below 

arr = Application.Transpose(roomCells) 'initialize the Variant as an array, filling it up with "roomCells" range content 

reportCell.Offset(row).Value = arr(1) & " in the " & arr(2) & " with the " & arr(3) & "." 'write the report line 

weapon = arr(3) ' store the weapon value to pass back to calling sub 

row = row + 1 'update the row for subsequent use 

End Sub 



Sub UpdateWeaponsStats(weapon As String, can As Long, dag As Long, lead As Long, rev As Long, rop As Long, wre As Long) 

' use "Select Case" pattern to avoid multiple and unuesful If-then repetition 
' once a "case" is hit, its correspondant statements will be processed and then control passes to the statement following the "End Select" one 
Select Case weapon 
    Case "Candlestick" 
     can = can + 1 
    Case Is = "Dagger" 
     dag = dag + 1 
    Case "Lead Pipe" 
     lead = lead + 1 
    Case Is = "Revolver" 
     rev = rev + 1 
    Case "Rope" 
     rop = rop + 1 
    Case Is = "Wrench" 
     wre = wre + 1 
End Select 

End Sub 



Sub WriteFinalStats(can As Long, dag As Long, lead As Long, rev As Long, rop As Long, wre As Long, finalStatsRng As Range, leastStatsRng As Range) 

Dim total As Long, least As Long 
Dim weaponArr As Variant 

total = can + dag + lead + rev + rop + wre 
weaponArr = Array(can, dag, lead, rev, rop, wre) 
With finalStatsRng.Resize(6) ' select a range of 6 cells in one clolumn, starting from the passed "finalStatsRng" range and resizing it up to enclose the subsequent 5 cells below it 
    .Value = Application.Transpose(weaponArr) ' fill the selected range (using ".Value" property of the "Range" object) with the "array" technique 
    With .Offset(, 1) ' shift one column to the right of selected range 
     .FormulaR1C1 = "=RC[-1]/" & total ' write in all cells a formula that takes the value form the adjacent cell and divide it by the "total" variable value 
     .Value = .Value ' have formulas replaced with values. you can comment this and cells will remain with formulas (they show the resulting values, but if you select one of them you'll see a formula in the formula ribbon of Excel UI 
    End With 
End With 

leastStatsRng.Value = Application.WorksheetFunction.Min(weaponArr) 'get the minimum value of all passed values calling the "MIN" function (which belongs to "WorksheetFuncion" object of the "Application" object -Excel) over the array filled with weapon countings 

End Sub 

上面的代码图案具有以下目标:

  • 断点代码到特定功能或潜艇

    让您更好地控制代码的流动,通过“main”子(这应该是一个像“Call DoThis()”,“Call DoThat()”等语句的序列)并专注于特定的潜艇/函数来处理特定的工作

    从而导致更容易维护和“可调试”代码

  • 只使用一些(出许多)有关VBA和Excel VBA技术,如使用Range对象(参见Resize(),Offset(),End(),SpecialCells()方法),数组(通过Variant类型变量),WorksheetFunction对象。

    当然你需要研究所有这些技术(和其他许多技术!)利用这些资源为SO本身,MSDN网站(https://msdn.microsoft.com/en-us/library/office/ee861528.aspx)和许多其他你轻松搞定在网页只是谷歌上搜索一个显著问题

为最终(和悲伤)的说明,我必须提醒你:建设游戏是最终导致“真正的”OOP的东西,就像VBA不是。

应该“建设游戏”是你的真正目的,那么你最好立即切换到一些真正的面向对象的语言,如C#和记者IDE,如Visual Studio(其社区版的版本目前是免费的)