VBA固定溢出行

VBA固定溢出行,vba,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

我是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
子线索()
模糊的名字、房间、武器
Dim can、dag、导线、转速、rop、wre、总计,至少为双精度
将行设置为整数
细胞(1,1)。激活
凸轮=0
dag=0
领先=0
rev=0
rop=0
wre=0
行=1
直到IsEmpty(ActiveCell)为止
name=ActiveCell.Value
room=ActiveCell.Offset(1,0).Value
武器=活动单元。偏移量(2,0)。值
单元格(第3行)。Value=name&“在带有“&武器&”的“&房间&”中
如果武器=“烛台”,则
can=can+1
如果结束
如果武器=“匕首”,则
dag=dag+1
如果结束
如果武器=“铅管”,则
铅=铅+1
如果结束
如果武器=“左轮手枪”,则
rev=rev+1
如果结束
如果武器=“绳索”,则
机械钻速=机械钻速+1
如果结束
如果武器=“扳手”,则
wre=wre+1
如果结束
ActiveCell.End(xlDown).End(xlDown.Activate
行=行+1
环
总计=can+dag+导线+rev+rop+wre
单元(2,6)=can
单元(3,6)=dag
电池(4,6)=铅
单元格(5,6)=修订版
单元(6,6)=rop
单元(7,6)=wre
单元格(2,7)=罐/总罐
单元格(3,7)=dag/总数
单元(4,7)=铅/总
单元格(5,7)=修订/总计
单元格(6,7)=rop/总计
单元格(7,7)=wre/总数
至少=100000000
如果can<最小值,则最小值=can
如果dag
我试图使用某些输入在一行上打印一个句子,但随着输入的变化,我想在下一行上打印下一个句子(因此,行=行+1),但它一直说存在“溢出”问题,我需要更改一些内容,但我不知道为什么。有人知道吗


谢谢

一旦读取了32K行,可能会出现溢出

这是因为您将
变量声明为
整数

将其更改为
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.

返回一个
,而不是
整数

注意
以字符串形式显示姓名、房间、武器

仅将
武器
定义为
字符串
,其余为
变体

正确的语法是
Dim name as string,room as string,willer as string

我喜欢这个“游戏”式的问题,而且,既然你宣称自己是“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技术,如使用
    范围
    对象(请参见
    调整大小()
    偏移量()
    结束()
    特殊单元格()
    方法),数组(通过
    变量
    类型变量),
    工作表函数
    对象

    当然,您需要学习所有这些技术(以及许多其他技术!),利用诸如SO本身、MSDN site()等资源,以及通过谷歌搜索一个重要问题就可以在web上轻松找到的许多其他资源

作为最后一点(也是令人悲伤的),我必须警告您:构建游戏最终会导致“真正的”OOP,而VBA则不是


如果“构建游戏”是您真正的目标,那么您最好立即切换到一些真正的OOP语言,如C#,以及相应的IDE,如Visual Studio(其社区版目前是免费的)

将行定义为长数据类型
Dim row as Long
将解决此问题。在模块的最顶端添加
选项Explicit
-您已将
can
声明为变量,并将值设置为
cam