2017-06-28 1 views
2

VBAが新しくなった。 私は各値の最初の数に応じて、一連の値に接頭辞を追加しようとしていました。 しかし、私はライン4でタイプミスマッチエラーが発生します。私は、変数にLeft()を使用しようとしていると仮定し、文字列(またはそのようなものの何か)に使用するはずです 私はそれを達成する?変数に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 
+1

関連はありませんが、コードが適切にインデントされていると、コードを読みやすく保守しやすくなります。あなたが持っている答えに 'If ... End If'と' For ... Next'が表示されます。あなたがそれを行う方法がわからない場合は、私の[Rubberduck](http://rubberduckvba.com/indexation)があなたのためにできることを見てみましょう。一貫してプロジェクト全体をインデントし、宣言されていない変数などを特定する)。 –

答えて

2
Testvariable = Range("A1", "A" & a) 

Testvariable事前にありがとうございます(ここではあなたのケースではありませんa=1、しない限り)

Leftは数字を受け入れるのに十分な柔軟性があり配列です文字列に加えて、配列ではありません。

3

トラブルは、あなたがleftstringを希望する場合、setキーワードを指定せずに割り当てられたときにあなたの配列を与えるために起こるRangeオブジェクトの左側を取るしようとしているです。

ここでは、範囲を文字列に変換して左に渡す方法について説明します。 How can I convert a range to a string (VBA)?

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 

また、常に正しく変数を宣言するようにしてください。手段は、タイプvariantaという変数を作成し、それをUsedRange.Rows.Count

Testvariable = Range("A1", "A" & a)手段の値種類variantTestvariableと呼ばれる変数を作成し、それに範囲オブジェクト(配列)の.valueを与えるを与える

a = UsedRange.Rows.Count

これらは

dim a as long 
    a = UsedRange.Rows.Count 
    dim Testvariable as string 
    Testvariable = Range("A1", "A" & a) 

正しく宣言していた場合

Testvariableの割り当ては失敗し、配列を文字列に変換できないことを伝えるより明らかなエラーが発生します。

+1

実際にはオブジェクトではありませんが、 'Set'キーワードを使用して割り当てられていないため、配列です。 –

+1

Range型のオブジェクトを返すように表示されます。 https://msdn.microsoft.com/VBA/Excel-VBA/articles/range-object-excel いずれにしても、文字列ではありません。 –

+2

'Range'関数はRangeオブジェクトを返しますが、' Set'キーワードなしで 'Testvariable'変数に代入すると' .Value'への暗黙の呼び出しが行われ、結果は配列になります。 'Set'キーワードなしでオブジェクトを割り当てることはできません。はい、それは文字列ではなく、答えは有効ですが、この微妙な部分だけが分かります:) –

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 

私が問題だったと思うが、他の2つの答えに加えて、あなたは、各セルの値に基づいてセル出力何かをループする必要があるということでした。したがって、あなたのコードをあなたのforループの真上に投げ込んで、必要に応じて変更してください。

1

VBAは「物事をより簡単に」するために背中の背後にある多くのことをしています。問題は、これらのことが戻って来て、後であなたをかむことです。

たとえば、宣言されていない変数です。 Option Explicitが各モジュールの先頭に指定されていないと、VBAは宣言されていない変数を使用するコードをうまくコンパイルします。役に立った?タイプがの場合、が推測されます。しかし、代わりにVBAはオンザフライVariantを宣言します。これは、あなたが何を入れても(そしてあなたが割り当てているものに合わせてそのタイプを変更します)。

a = UsedRange.Rows.Count 
ここ

a暗黙のVariant/Longです。 、さらに良い

Dim a As Long 

それに意味のある名前を与える: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.Valueは、複数の単一のセルを参照していることを、1ではないでしょうので、 - Excelのオブジェクトモデルを使用すると、すべての値を含む配列を与えます指定された範囲の細胞であり、それはTestvariableに含まれています。あなたは範囲だけではなく、それらの値を参照するためにTestvariableを望んでいた場合

は、あなたがRangeオブジェクト変数を宣言し、Setキーワードとそれを割り当てます:

Dim testVariable As Range 
Set testVariable = ActiveSheet.Range("A1:A" & a) 

お知らせここに明示的ActiveSheet:それがなければ、コードはまったく同じことなので、なぜそれを入れますか?あなたはできるだけ明示ようになりたいので: - そしてそれはバグのさらに別のソース(ちょうどグーグル、「範囲エラー1004」、あなた」だ、修飾されていないRangeCellsRowsColumnsNamesはすべて暗黙的にアクティブなワークシートを参照して呼び出しますスタックオーバーフローに関する何百もの質問があります)。

あなたは値その指定された範囲内のすべてのセルのを含むように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では、このようなエラー値も暗黙的に変換できません。

セルの値を読み取る前に、にはを必ず入力する必要があります。 (1, 1)こと

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) 

お知らせ:そのためIsError機能を使用できますか? testVariableは1ベースの2D配列です(Option Base 1の暗黙的なサイズの配列はRangeから取得する場合を除いて常に0ベースです)、最初の行/最初の列の値を読み取るには、インデックス(1, 1)の値を読んでください。

しかし、それはあなたがやろうとしていることではありません。

は、だから私は、各値の最初の数に応じて、値のセットに接頭辞を追加しようとしていました。

「各値」とは、値を繰り返し処理する必要があることを意味します。ループがあることを意味します。

Dim i As Long 
For i = 1 To a 
    '... 
Next 

それは私たちが望む「最初の数」ではない、それは我々がをループしているすべてのセルのfirstDigitです。ここで

If FirstNo(i,1) = "1" Then 

あなたが扱っている種類のトラックを失ってしまった:FirstNoはループが開始するので、その値はすべての反復で一定となりますを割り当てられていました。

あなたがこれを行うことを意味:今すべてが、それは何が起こっているのか確認するためにはるかに簡単だ、明示的で適切にインデントされる...そしてあなたがするVBAを必要とする理由、今、私は真剣に質問したいこと

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 

をその:

[B1] = IFERROR(IF(LEFT(A1, 1) = "1", "abc" & A1, "def" & A1), "") 

数式をドラッグします。

+0

非常に詳細な説明をありがとう。 'Testvariable'が範囲を参照する違いは何ですか? 範囲の場合、usedRows = 5の場合、 'Testvariable'はA1:A5 となりますが、値の場合は ' Testvariable'が実際の値になりますか? このコードの目的のために範囲と値の両方を試していますが、範囲または値のどちらも同じです。 – kct360

+0

もし 'Range'ならば、あなたは状態とメソッドを持つ*オブジェクト*を見ています。それが値の配列であれば、それはすべてです。値を必要とし、それ以外のものが必要な場合は、配列を操作してください。オブジェクトとそのメンバーが必要な場合は、 'Range'を使って作業してください。すべてと同じように、#ItDepends。 –

+0

本当に何を意味しているのかは分かりませんが、もっと経験があれば、私は本当に理解することができます。私はVBAを試みる前にExcelで数式を実行しました(エクセル式からVBAに変換して自分のコードを入力すると良い方法だと思っていましたが、予想以上に複雑/複雑ですこの例では) – kct360

関連する問題