我是VBA的新手。 所以我试图将前缀附加到一组值,具体取决于每个值的第一个数字。 但是我在第4行遇到类型不匹配错误。我想这是因为我试图在一个变量上使用Left(),它应该用在一个字符串上(或者某种类似的东西?) 我如何实现这一目标?
提前谢谢
Sub test()
a = UsedRange.Rows.Count
Testvariable = Range("A1", "A" & a)
FirstNo = Left(Testvariable, 1)
For i= 1 To a
If FirstNo(i,1) = "1" Then
Cells(i,2) = "abc" & FirstNo(i,1)
Else Cells(i,2) = "def" & FirstNo(i,1)
End if
Next
End Sub
答案 0 :(得分:3)
麻烦的是,当Range
想要set
left
时,您正试图在string
对象的左侧,在没有Sub test()
dim a as long
a = UsedRange.Rows.Count
dim Testvariable as string
Testvariable = RangeToString(Range("A1", "A" & a))
dim FirstNo as string
FirstNo = Left(Testvariable, 1)
dim i as long
For i= 1 To a
If FirstNo(i,1) = "1" Then
Cells(i,2) = "abc" & FirstNo(i,1)
Else
Cells(i,2) = "def" & FirstNo(i,1)
End if
Next
End Sub
Function RangeToString(ByVal myRange as Range) as String
RangeToString = ""
If Not myRange Is Nothing Then
Dim myCell as Range
For Each myCell in myRange
RangeToString = RangeToString & "," & myCell.Value
Next myCell
'Remove extra comma
RangeToString = Right(RangeToString, Len(RangeToString) - 1)
End If
End Function
关键字的情况下分配给您一个数组}。
这篇文章解释了如何将范围转换为字符串,然后可以传递给左边。 How can I convert a range to a string (VBA)?
a = UsedRange.Rows.Count
另外,请务必正确声明变量。
a
表示创建一个名为variant
的{{1}}类型的变量,并为其赋值UsedRange.Rows.Count
Testvariable = Range("A1", "A" & a)
表示创建名为Testvariable
的{{1}}类型的变量,并为其指定范围对象的variant
(数组)
如果这些被正确宣布
.value
Testvariable的赋值将失败并出现更明显的错误,通知您无法将数组转换为字符串。
答案 1 :(得分:2)
Testvariable = Range("A1", "A" & a)
Testvariable
是一个数组(除非a=1
,这不是你的情况)
Left
足够灵活,可以接受除字符串之外的数字,但不接受数组。
答案 2 :(得分:1)
如果我遵循你的流程,我认为这会让你得到你想要的东西。
Sub test()
Dim ws As Worksheet
Set ws = ActiveWorkbook.ActiveSheet
a = ws.UsedRange.Rows.Count
TestVariable = Range("A1", "A" & a)
For i = 1 To a
FirstNo = Left(TestVariable(i, 1), 1)
If FirstNo = "1" Then
Cells(i, 2) = "abc" & FirstNo(i, 1)
Else
Cells(i, 2) = "def" & FirstNo
End If
Next i
End Sub
我认为问题是,除了其他两个答案之外,你需要循环遍历细胞和根据每个细胞值输出一些东西。因此,只需将代码放在for
循环内部,然后根据需要进行更改。
答案 3 :(得分:1)
VBA在你背后做了很多事情,以“让事情变得更轻松”。问题是这些东西会回来后再咬你。
例如,未声明的变量。如果在每个模块的顶部都没有指定Option Explicit
,VBA将很乐意编译使用未声明的变量的代码。听起来有用吗?如果类型推断,那就是。但是相反,VBA声明了一个动态Variant
,它保存你放入它的任何东西(并改变它的类型以容纳你指定的任何东西)。
a = UsedRange.Rows.Count
此处a
是隐式Variant/Long
。将其声明为Long
整数:
Dim a As Long
更好的是,给它一个有意义的名字:
Dim usedRows As Long
usedRows = UsedRange.Rows.Count
现在有趣的部分:
Testvariable = Range("A1", "A" & a)
此处Testvariable
是隐式Variant/Array
。怎么会这样? VBA看到的代码如下所示:
Testvariable = Range("A1", "A" & a).Value
由于a
不是1
,.Value
指的是多个单个单元格 - Excel的对象模型会为您提供一个包含所有单元格值的数组指定的范围,这就是Testvariable
包含的范围。
如果您希望Testvariable
引用范围而不只是引用它们的值,您将声明一个Range
对象变量,并为其分配Set
} keyword:
Dim testVariable As Range
Set testVariable = ActiveSheet.Range("A1:A" & a)
注意这里的显式ActiveSheet
:没有它,代码完全相同,所以为什么要把它放进去?因为您希望尽可能显式:不合格的Range
,Cells
,Rows
,Columns
和Names
会隐式调用请参阅活动工作表 - 这是另一个错误来源(只是google up“范围错误1004”,你会发现数百个Stack Overflow问题)。
如果您希望testVariable
包含指定范围内每个单元格的值,那么您将声明并指定testVariable
,如下所示:
Dim testVariable As Variant
testVariable = ActiveSheet.Range("A1:A" & a).Value
现在你有一个数组,其中包含活动工作表范围"A1:A" & a
中的所有值:这就是你的代码所做的...隐式。
FirstNo = Left(Testvariable, 1)
所以现在我们想要“第一个数字”,我们正在从变量数组中读取它。
Left
(或Left$
)函数来自VBA.Strings
模块,意味着使用字符串;它也可以与其他类型一起使用(使用隐式类型转换),但是如果你给它一个对象引用或一个数组,它将不知道如何为你转换它,并且VBA将引发一个运行时错误。
testVariable
变量数组包含Variant
个值:大多数单元格将包含Double
个浮点值。其他人将包含String
。某些单元格可能包含错误值(例如#N/A
,#VALUE!
或#REF!
) - 并且VBA也无法隐式转换此类错误值。
因此,在您阅读任何单元格的值之前,您需要确保可以读取它;使用IsError
函数:
If IsError(testVariable(1, 1)) Then
Exit Sub ' cell contains an error; cannot process
If Not IsNumeric(testVariable(1, 1)) Then
Exit Sub ' cell doesn't contain a number; cannot process
End If
' now that we KNOW our value is a numeric value...
Dim firstNumber As Double
firstNumber = testVariable(1, 1)
请注意(1, 1)
?这是因为testVariable
是一个基于1的2D数组(没有Option Base 1
隐式大小的数组总是从0开始,除非你从Range
获得一个数组,所以要阅读在第一行/第一列中的值,您需要读取索引(1, 1)
处的值。
但那不是你想要做的。
所以我试图将前缀附加到一组值,具体取决于每个值的第一个数。
“每个值”意味着你需要迭代这些值,所以你有一个循环。
Dim i As Long
For i = 1 To a
'...
Next
这不是我们想要的“第一个数字”,而是我们循环的每个单元格的firstDigit
, 。
If FirstNo(i,1) = "1" Then
在这里,你已经忘记了你正在处理的类型:在循环开始之前,FirstNo
被分配了,所以它的值在每次迭代时都是常量。
你的意思是这样做:
Dim values As Variant
values = ActiveSheet.Range("A1:A" & usedRows).Value
Dim i As Long
For i = 1 To usedRows
If Not IsError(values(i)) Then
Dim representation As String
representation = CStr(values(i))
Dim prefix As String
If Left$(representation, 1) = "1" Then
prefix = "abc"
Else
prefix = "def"
End If
ActiveSheet.Range("B" & i).Value = prefix & representation
End If
Next
现在所有内容都是明确的并且正确缩进,更容易看到发生了什么......现在我要认真地质疑为什么你需要VBA来做到这一点:
[B1] = IFERROR(IF(LEFT(A1, 1) = "1", "abc" & A1, "def" & A1), "")
然后拖下公式。