こんばんは。

EXCEL VBA で困っております。

シートから配列にコピーさせると、ReDimで設定してあったIndex番号が
なぜか替ってしまうらしいのです。
いろいろと検索してみましたが、どうしても見つからず、ここで質問させていただくことにしました。

下記のコードで確認してみてください。

Sub test()

Dim A As Variant
ReDim A(1 To 1, 0 To 4)

For j = 0 To 4
A(1, j) = j
Next j

Range("A1:E1") = A

MsgBox A(1, 0) 'ちゃんと機能して(1, 0)の位置で[0]と表示
'MsgBox A(1, 5) '←インデックスが有効範囲にありません

A = Range("A1:E1")

Range("A2:E2") = A

'MsgBox A(1, 0) 'さっき機能したのに今度はエラー
MsgBox A(1, 1) '(1, 1)はセルでは2列目の[2]が取得されない
MsgBox A(1, 5) 'さっきエラーになった(1, 5)は今度はエラーにならない

End Sub

なぜ、A(1 to 1, 0 to 4) が A(1 to 1, 1 to 5) と替ってしまうのか?
シート範囲全体をいっぺんに配列に格納するとこういうことが起こるのが仕様なのか??
自分の推測では、配列は[0]から始めることができますが、
シート上では[0]という開始位置を認識できないため、
Variant変数型のなかで自動的に書き換えちゃってくれてるのかな?
なんて思ったりしました。
理由がわかる方、おりましたらご教授くださいませ。

また、どうしても、この2次元配列で、
てっとり早いこのコピーコードを使いセル範囲から配列へコピーさせて、
列方向へのIndexを (0 to 4)とさせたいのですが、
何かよい方法はありますでしょうか??
For文やEach文でひとつずつセルから配列へ格納という方法もあるかもしれませんが、
実際に打ち込んでいるコードは、行列ともかなり範囲が広いために、
処理時間を気にしてしまいます。

そこそこ使い慣れてきたのに、よもやこんなところで、躓くの!?といった心境です。
ご指南のほど、どうぞよろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (5件)

>この (1 to 5) を再び (0 to 4) へ復活


残念ながら、VBAは配列操作がしょぼいのでForループするしか。
なるべく、セルと直結した配列は(1 to n)で統一したいです。

◆処理速度@Forループに向けて
配列はアクセスが早いから誤差!…らしいよ。試した↓

 '処理1: 10000×100のセル範囲取得@セルには英字100字
 a1 = Range("A1:CV10000")  '-> 約1500ms
 '処理2: Forループで配列複製
 a2(r, c) = a1(r + 1, c + 1)   '-> 約450ms

450ms!30%増?思ったよりかかったΣ(゜□゜;)
…けど、ちょっと処理を変えるだけで大きく変わるんです。

 処理1' 1×100のセル取得、を10000回 -> 250ms
 処理2' 1×100の配列複製、を10000回 -> 100ms

…なんででしょうね(苦笑)
これなら、高速化は、他の処理を見直した方が大きいかも。
特に、後者(2')の使い方なら、100msは許容範囲では?
お試しあれ

◆補足説明
◇配列について
A = Rangeでは、以下と同じことが起きてます。
 ReDim a1(0 to 10): ReDim a2(1 to 20)
 a1 = a2 'a1はa2の複製、つまり(1 to 20)になる

ちなみに、Array関数などは必ず(0 to n)の配列を返します。
"Option Base 1"なんて設定しても、ソレは変わりません。
セル絡みは1から、他は0からで慣れてクダサイ。

◇Rangeについて
Rangeはオブジェクトなので、仕様ですね。
・Range.Valueの返却値は、範囲の場合、(1 to n)の配列です。
・Range.Valueへの代入は、範囲の場合…こんな感じ↓
  ReDim A(101 to 103)
  Range("A1:C1") = A 'A1セルにはA(101)が入る
    • good
    • 0
この回答へのお礼

みなさま、ご回答ありがとうございました。

プログラム制作の最初の段階で、配列範囲を0から始める構造にしてしまったため、なんとかIndexの設定を維持したかったのですが、
仕様ならしょうがありませんでした…。
打開策として、大きな範囲を配列に一変に格納したあと、別の配列にFor文で、データを一個一個、再配置してみました。
シートとのやり取りではなく、配列同士のやり取りなので、そんなに時間がかからないことがわかりました。

ありがとうございました。

お礼日時:2011/04/27 18:17

LBOUND(A)やUBOUND(A)とかを使えばどうでしょう?


これを使えば、0始まりとか1始まりとかを気にしないでコーディングできますが・・・。

これだと都合悪いですか?
    • good
    • 0

そもそも、単純な Range 指定は Excel.Range オブジェクトを取得します。


 Dim rng As Excel.Range
 Set rng = Range("A1:E1")
 Debug.Print rng.Address
VB が勝手にデフォルトプロパティを利用して配列に変換してるようですが、
そもそも、そこに省略されている処理があるので、プログラムとして
あまり良くないと思います。

配列で処理したいなら、Value プロパティなどで取得・設定します。
 Range("A1:E1").Value = A

上記プロパティを利用するとプロパティ内部で「セルの範囲に応じた
新しい配列」を作成して返すので、別の配列になります。
無視されたというより、入れ物自体が違います。新しく作られます。

そして、Excel では配列の要素は 1 始まりになります。これは仕様です。
配列自体は、VBA 固有のものではなく、VB の文法に応じて利用できるので
プログラムコードのみの利用では 0 の要素も使えますが、Excel の
セルを操作した時点で Excel の都合の良い形に解釈されます。

 Range("A1:E1").Value = A
設定する時は A が
 ReDim A(1 To 1, 0 To 4) であっても
 ReDim A(1 To 1, 1 To 5) であっても
指定した Range 範囲の先頭からデータが入ってしまいます。
 ReDim A(1 To 1, 0 To 4)
 For j = 0 To 4
  A(1, j) = j
 Next j
 ReDim Preserve A(1 To 1, 0 To 4)
 Range("A1:E1").Value = A
 ReDim Preserve A(1 To 1, 1 To 5)
 Range("A2:E1").Value = A

バグのもとですので、配列の Index の下限は 1 で統一する事を
お勧めします。
    • good
    • 0

私は習得出来てないため、いつも色々説明をNETなどで読んでも、何か歯切れが悪いですが


http://officetanaka.net/excel/vba/variable/09.htm
などをじっくり読んで見てください。
とくに>たとえ事前に要素数がわかっていても、次のように要素数が固定されている配列に代入することはできません。のあたり。
なぜか知りたいが、解説本には記事は無く、WEBでも出あわさない。
別の記事に>配列を複写するときは、あくまで「値渡し」をしているということです。「参照渡し」はしていないので注意が必要です。あるが、
何か関係があるのかな。
ーー
参考になるかどうか
Sub test03()
Dim MyStr1 As Variant
MyStr1 = Range("A1:e1")
Range("A5:E5") = MyStr1
MsgBox IsArray(MyStr1)
End Sub
はTRUE、A1だけだとFalse
ーー
Sub test02()
Dim A As Variant
A = Range("A1:E1")
Range("A4:E4") = A
'以上はOK
A = Array(Range("A1"), Range("B1"), Range("C1"), Range("E1"))
For i = 0 To UBound(A)
MsgBox A(i)
Next
End Sub
こうするとOK
    • good
    • 0

>なぜ、A(1 to 1, 0 to 4) が A(1 to 1, 1 to 5) と替ってしまうのか?



A = Range("A1:E1")
としているからです。
これは、配列要素への代入ではなく、配列変数への代入です。
配列変数へ代入すると、その前の定義していたReDimは無視され、新しく配列の範囲が定義されます。

新しい配列は、行の範囲は1からRangeの行数、列の範囲は1からRangeの列数になります。

A = Range("A1:E1")
と代入しても、
A = Range("C5:G5")
と代入しても、配列の範囲は同じです。

また、
A = Range("C5:G7")
とすると、Aは(1 To 3, 1 To 5)の配列になります。
    • good
    • 0
この回答へのお礼

さっそくのご回答ありがとうございます。

ReDimが無視されてしまうんですね。。。

なんとなく、シート間と配列間では、そういったわだかまりみたいなものに、
いままでも、何度となく振り回されてきたような気がしますw。

これは仕様みたいなものですよね?
それであれば、(0 to 4) から (1 to 5)への変更は致し方ないとして、
この (1 to 5) を再び (0 to 4) へ復活させることは可能なのでしょうか?

シート範囲と配列領域のやり取りで、For文やEach文を使うのは、懸念してしまうのですが、配列領域と配列領域でのFor文のやり取りなら、まだ我慢できそうです。

やはり、新しく配列を用意して、新しい配列にデータ転送する他には、
うまい方法はないのでしょうか??

みなさまの知恵をお借りできたら幸いです。
どうぞ、よろしくお願いいたします。

お礼日時:2011/04/21 23:45

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qドラマのギルティの始まりにラップ?の英語の曲が流れるんですが誰の曲かわ

ドラマのギルティの始まりにラップ?の英語の曲が流れるんですが誰の曲かわかりますか?

Aベストアンサー

ヒップホップ調のオープニング曲であれば、音楽担当の住友紀人さんの作曲らしいです。
私が使っている着メロサイトで提供されているんですが、そう書いてありました。
たぶん、サントラが出れば確認できると思います。

QVBA 配列計算について 配列の入力に配列の使用

配列に複数のセル値の合計値を設定したいと思っています。
求める合計値は複数あるため、出力も配列となります。
そこで下記のようにプログラムを考えたのですが、全て同じ値の配列として出力されてしまいます。
VBAではC言語のように配列の古い値に足していくことはできないのでしょうか?

(sum()は0で初期化) (10個飛ばしのデータの合計値を算出)
For i = 0 To 10
For j = 0 To 5
sum(i)= sum(i) + Worksheets(sheetname).Cells(10, 3).Offset(j * 10, 0).Value
Next i
Next j

出力配列例 全て同じ値になってしまいます・・・
1.254
1.254
1.254
・・・

回避方法もしくはうまい計算方法などありませんでしょうか

Aベストアンサー

なにを計算したいんでしょうか?

このコードでは、どのSum(i)にも、
Cells(10,3).Value + Cells(20,3).Value + ・・・・ + Cells(60,3).Value
の値が入るから、同じになるのは当然です。

i ごとにSum(i)を変えたいのなら、
Worksheets(sheetname).Cells(10, 3).Offset(j * 10, 0).Value
の中のどこかに i が入ってないと・・・・

Q日本の英語教育の始まり

タイトルどおりです。
異文化理解教育についてちょっとしたレポートを作成中(期限は明日、しかし白紙・・・)なのですが、英語教育の変遷を述べる必要があって、いつから始まったのかしらと調べています。手元の資料では1958年かなぁと読み取れるのですが、いかがでしょう?

Aベストアンサー

  日本英語教育史というサイトがあります。
明治元年(1868)からとなってます。

また津田塾大学創設された津田梅子を調べてもいろいろ参考になると思います。

参考URL:http://www.hiroshima-pu.ac.jp/~umamoto/e-kyoikushi/n-meiji.htm

QExcelセルにVBAでINDEX関数を入力

ExcelでINDEX関数とMATCH関数で"B11:E13"セルに以下の数式データがあります。

数式は
"B11"=IF(ISERROR(INDEX($A$1:$A$9,MATCH(1,B$15:B$23,0))),"",INDEX($A$1:$A$9,MATCH(1,B$15:B$23,0)))


"B12"=IF(ISERROR(INDEX($A$1:$A$9,MATCH(2,B$15:B$23,0))),"",INDEX($A$1:$A$9,MATCH(2,B$15:B$23,0)))

"B13"=IF(ISERROR(INDEX($A$1:$A$9,MATCH(3,B$15:B$23,0))),"",INDEX($A$1:$A$9,MATCH(3,B$15:B$23,0)))

"C11"==IF(ISERROR(INDEX($A$1:$A$9,MATCH(1,C$15:C$23,0))),"",INDEX($A$1:$A$9,MATCH(1,C$15:C$23,0)))



"B15~B23"に数値1~3を入力した場合イニシャルA~I が入力される式ですが、列を連続で入力できるような処理をVBAのWorksheetFunctionで行うにはどのようにコードを記述すればよいのでしょうか。
ご回答のほどよろしくお願いします。

ExcelでINDEX関数とMATCH関数で"B11:E13"セルに以下の数式データがあります。

数式は
"B11"=IF(ISERROR(INDEX($A$1:$A$9,MATCH(1,B$15:B$23,0))),"",INDEX($A$1:$A$9,MATCH(1,B$15:B$23,0)))


"B12"=IF(ISERROR(INDEX($A$1:$A$9,MATCH(2,B$15:B$23,0))),"",INDEX($A$1:$A$9,MATCH(2,B$15:B$23,0)))

"B13"=IF(ISERROR(INDEX($A$1:$A$9,MATCH(3,B$15:B$23,0))),"",INDEX($A$1:$A$9,MATCH(3,B$15:B$23,0)))

"C11"==IF(ISERROR(INDEX($A$1:$A$9,MATCH(1,C$15:C$23,0))),"",INDEX($A$1:$A$9,MATCH(1,C$15:C$23,0)))...続きを読む

Aベストアンサー

続けてお邪魔します。

エラー処理について・・・

安直な方法ですが
↓のコードにしてみてください。

Sub Sample2()
Dim i As Long, j As Long
On Error Resume Next '←おまじないでこの行を追加
For j = 2 To 5
For i = 1 To 3
Cells(i + 10, j) = WorksheetFunction.Index(Range("A1:A9"), WorksheetFunction.Match _
(i, Range(Cells(15, j), Cells(23, j)), False))
Next i
Next j
End Sub

これで1~3のデータがない場合でも何とか対処できると思います。m(_ _)m

Qこの英語・・・の意味

『全ての始まり』『人類の始まり』などの『~の始まり』は英語でなんて言うんですか?BEGINNINGでいいんですか?

Aベストアンサー

『人類の始まり』・・・『Human race's start』
『全ての始まり』・・・『All starts』

なので、startを使うみたいです。

参考URL:http://www.excite.co.jp/world/english/

Q[VB6/VBA] Variant型配列リテラルの書き方

http://oshiete1.goo.ne.jp/qa4043791.html
の#1のURIに
http://exceler.blog68.fc2.com/blog-entry-20.html

Dim a() As Variant // As Variant追加。As Integerとかは無理っぽい
a = [{32,5,0}] //これ

というような表記があるのですが,msdn.comもしくはmicrosoft.comのどこかに,この書き方に関する解説はありますか?

VB.NETで
Option Explicit On
Option Compare Binary
Option Strict On
Option Infer Off
Module Program
Sub Main()
Dim a() As Integer
a = new integer(){1,2,3}
End Sub
End Module

というような書き方が出来るのは知っているのですが。

Aベストアンサー

ExcelVBAの機能用ですよ
『Microsoft Excel x.xx Object LIBRARY』を参照設定してやると
ご質問のような記述が可能になるようです

公式なドキュメントは見つけられませんでした
VB付属の MSDNで『配列』『リテラル』を検索すると
ExcelのApplicationオブジェクト Internationalプロパティの中に
『配列リテラル』を見つける事が出来ました

Q英語ですべてのはじまりって?

英語で「すべての始まり」って分からないんです。
英語圏で生活の方。自信のあるかたよろしくお願いします。

Aベストアンサー

gen・e・sis
1 起源, 起こり, 発生, 生成, 創始; 発生の様式[由来].
・the ~ of the novel その小説の起源.
2 [G*] 【聖】 創世記 《旧約聖書の第 1 書

genesisが、一番良く使われるのではないでしょうか。
ご存知かもしれませんが神が世界を作るところから聖書は始まります。

QExcel VBA 文字列を配列にて格納

初心者なので、申し訳ございません。
使用しているOS WinXP、アプリケーション Excel2003

保存してあるtxtファイルに入っている文字列を、重複するデータをグループ化して、最終的に別のtxtファイルにて出力するのですが、最初の配列して格納するところから分かりません。

参考までに・・・
入力ファイル「InputData.txt」
相川
関本
川上
関本
久保
相川
川上
久保
青木

出力ファイル「Group.txt」
相川
関本
川上
久保
青木

今のところは、ここまでやっています。
Dim A As String
Dim myText2 As String
A = Dir("InputDate.txt")

If A = "InputDate.txt" Then
Open A For Input As #1
Do While Not EOF(1)
Input #1, myText2
myText = myText & myText2
Loop

Open "Group.txt" For Output As #2

よろしくお願いします。

初心者なので、申し訳ございません。
使用しているOS WinXP、アプリケーション Excel2003

保存してあるtxtファイルに入っている文字列を、重複するデータをグループ化して、最終的に別のtxtファイルにて出力するのですが、最初の配列して格納するところから分かりません。

参考までに・・・
入力ファイル「InputData.txt」
相川
関本
川上
関本
久保
相川
川上
久保
青木

出力ファイル「Group.txt」
相川
関本
川上
久保
青木

今のところは、ここまでやっています。
Dim A As String...続きを読む

Aベストアンサー

参考につくってみました。
一度、お試しください。

Sub uniq2()

Dim pFile As String
Dim pText As String

Dim pItem
Dim pPath As String
Dim pList() As String
Dim pFunc As Boolean
Dim i As Long, j As Long

pPath = ThisWorkbook.Path & "\"

pFile = Dir(pPath & "InputData.txt")

If pFile = "" Then Exit Sub

Open pPath & pFile For Input As #1
Do While Not EOF(1)
Input #1, pText

If pText <> "" Then
If i = 0 Then
ReDim pList(i)
pList(i) = pText
Else
For j = 0 To UBound(pList)
If pList(j) = pText Then
pFunc = True
Exit For
Else
pFunc = False
End If
Next j

If pFunc = False Then
ReDim Preserve pList(UBound(pList) + 1)
pList(UBound(pList)) = pText
End If

End If
i = i + 1
End If

Loop

Close #1

Open pPath & "Group.txt" For Output As #2
For i = 0 To UBound(pList)
Print #2, pList(i)
Next i
Close #2

End Sub

参考につくってみました。
一度、お試しください。

Sub uniq2()

Dim pFile As String
Dim pText As String

Dim pItem
Dim pPath As String
Dim pList() As String
Dim pFunc As Boolean
Dim i As Long, j As Long

pPath = ThisWorkbook.Path & "\"

pFile = Dir(pPath & "InputData.txt")

If pFile = "" Then Exit Sub

Open pPath & pFile For Input As #1
Do While Not EOF(1)
Input #1, pText
...続きを読む

Q英語で

英語で「私たちの始まり」とどのように表現するが良いのでしょうか?
Our beginningなのでしょうか?
ご教示よろしくお願いします。

Aベストアンサー

We've only just begun.

QExcel-VBAの配列「Public Const」について

Excel-VBAの配列「Public Const」について
変数「AA」に"メロン"を定義する方法として次の記述で対処しているのですが、
配列で定義する書き方が解りません!?
Public Const AA As String = "メロン"
配列変数「BB」に「"栗", "桃", "メロン"」を定義をしたいのですが、
どの様に記述すれば良いか教えて下さい。
以上

Aベストアンサー

下記なら可能のようだが
Public aa
Sub test01()
aa = Array("桃", "栗", "柿")
End Sub
Sub test02()
test01
For i = 0 To 2
MsgBox aa(i)
Next i
End Sub
何処がこれでは質問に適合してないのか、説明したら。聞きたいことが明確になり、具体的になるだろう。
aaはバリアント変数。
http://pc.nikkeibp.co.jp/article/NPC/20070803/279065/
に解説が有る。
バリアント変数利用が気に食わないのか?
aa()={"a","b","c"}のような書き方が、VBAでも出来ないかと聞きたいのか。


人気Q&Aランキング

おすすめ情報