VBからCSVファイルをExcelにWorkbooks.OpenTextで読み込ませる前にRangeでセルを移動しようとするとエラーとなってしまうのですが、Excelの2行目からCSVデータの挿入をすることは出来ないのでしょうか?
ExcelVBAでは何の問題もなかったのでできると思っていたのですが。
ちなみに、OpenText後にRengeでセルを移動することは可能なのですが。
よろしくお願いいたします。
> VBからCSVファイルをExcelにWorkbooks.OpenTextで読み込ませる前に
> Rangeでセルを移動しようとするとエラーとなってしまうのですが、
具体的にはどのようなコードを書いていて、それを実行すると、
何というエラーメッセージが現れるのでしょうか?
魔界の仮面弁士様
いつもありがとうございます。
エラーなのですが、'オブジェクト変数にオブジェクトの参照を代入した後で
Rangeにてセルを移動しようとすると
「実行時エラー1004 Rangeメソッドは失敗しました。」
というエラーになってしまいます。
下にコードを書きますのでよろしくお願いいたします。
Private Sub Command2_Click()
'CSVファイルの読込
Dim xlapp As Excel.Application
Dim FileName As String
Dim xlsheet As Excel.Workbook
'CSVファイルを拡張子を変更して読込
FileName = App.Path & "\test.csv"
'オブジェクト変数にオブジェクトの参照を代入
Set xlapp = New Excel.Application
xlapp.Range("A2").Select
→ここの部分でエラーになります
'各列のデータに合ったデータ型を指定して読み込み
xlapp.Workbooks.OpenText FileName:=FileName, _
DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
Comma:=True, FieldInfo:=Array(Array(1, xlTextFormat), _
Array(2, xlTextFormat), Array(3, xlTextFormat), _
Array(4, xlTextFormat), Array(5, xlYMDFormat), _
Array(6, xlGeneralFormat), Array(7, xlGeneralFormat), _
Array(8, xlGeneralFormat))
xlapp.Cells.Select '入力データの幅にセルの幅を
xlapp.Cells.EntireColumn.AutoFit '広げる。
xlapp.Range("A2").Select 'ホームポジションに移動
'Excel形式で保存する
xlapp.Workbooks("test.csv").SaveAs FileName:="test.xls", FileFormat:=xlExcel9795
xlapp.Visible = True 'Excelを表示
'コピー元の.csvを削除する
'Kill App.Path & "\test.csv"
Set xlapp = Nothing 'オブジェクトとの関連付けを解除
End Sub
> xlapp.Range("A2").Select
> →ここの部分でエラーになります
起動直後は、まだワークブック/ワークシートが無い状態ですから、
A2セルを選択しようにも、選択すべきセルが無い状態なのです。
もし、セルを操作したいのであれば、まずは xlApp.Workbooks.Add、ないしは
xlApp.Workbooks.Open などを使って、選択すべきセルを用意しておいてください。
そのすれば、Range操作が可能になります。
なお、特に理由が無い限りは、ApplicationオブジェクトのRangeメソッドは
使わない方が良いでしょう。
この場合はかわりに、WorkbookオブジェクトのRangeメソッドを使用してください。
Workbookを指定せずにセルを操作しようとした場合、どのシートのセルを
操作しているのかが曖昧になってしまいますので、気を付けて使わないと、
思わぬ誤動作を引き起こす原因になります。
# オブジェクトの指定を省略した場合、Excel VBAによる操作であれば、
# それは自分自身が持つオブジェクトを指している事が明確となりますが、
# VBから操作した場合は、どのオブジェクトを指しているのかを明示しないと、
# 新たなオブジェクト参照が内部的に生成されてしまうため、処理終了後も
# Excelが解放されずに、ゾンビとして残ってしまうことがあります。
なお、同様の理由で、Select系/Active系の命令も、できるだけ
使わないようにした方が無難です。
> Excelの2行目からCSVデータの挿入をすることは出来ないのでしょうか?
『挿入』ならば、Workbooks.OpenText()ではなく、QueryTableですね。
イメージとしては、
Dim objSheet As Excel.Worksheet
Dim objQuery As Excel.QueryTable
:
Set objQuery = objSheet.QueryTables.Add("TEXT;C:\TEST.TXT", objSheet.Range("B1"))
objQuery.TextFilePlatform = 932
:
objQuery.Refresh False
Set objQuery = Nothing
のような感じになります。
> この場合はかわりに、WorkbookオブジェクトのRangeメソッドを使用してください。
失礼。『WorkseetオブジェクトのRangeメソッド』の間違いです。m(_ _)m
魔界の仮面弁士様
いつも丁寧なご返事、ありがとうございます。
上記の内容を元にいろいろと試したりはしたのですが、
思うようにいきません。
まず、挿入というよりはExcelの2行目からデータを貼り付けたい
という意味で書いたのですが、これもやはりQueryを使う必要が
あるのでしょうか?
Workbooks.OpenText()は使えないということでしょうか?
あと、データを貼り付ける際、既存のファイルがあってCSVの値だけ
上書きで保存したいと考えているのですが、可能なのでしょうか?
申し訳ありませんが、よろしくお願いいたします。
OpenTextは、テキストファイルを1枚のシートとして、
それを含む新しいブックを開くメソッドですよね。
(Excelからの操作でいえば、[ファイル]-[開く]に相当します)
一方のQueryTableは、ワークシートに外部データ(例えばテキストファイル)を
貼り込むためのメソッドです。この場合、新規のワークシートを作成して、
そこに読み込ませるようにする事もできますし、既存のワークシートの
特定位置(例えば2行目…すなわち、A2セルから)に貼り込む事もできます。
(Excelからの操作でいえば、[データ]-[外部データの取り込み]にあたります)
> これもやはりQueryを使う必要があるのでしょうか?
使わなくても良いでしょうし、使っても良いでしょうね。お好きな方法でどうぞ。
今回記述した方法以外にも、やり方はいろいろ考えられるかと思いますので、
最終的に、ご自身の仕様にマッチしていると思われる手法を選択してください。
# たとえば(多少回りくどい方法ですが)、Openステートメントでファイルを開いて、
# それをDDEにてセルに埋め込んで行く……なんて方法なども考えられますし。
> Workbooks.OpenText()は使えないということでしょうか?
そんな事はないと思いますよ。ただしOpenTextの場合は、2行目に貼り込むという
機能はありませんから、OpenTextした後に、先頭に空行を挿入してやるようにするか、
もしくは、OpenTextした後に、その内容を別のシートの2行目以降にCopyする事になるかと。
> あと、データを貼り付ける際、既存のファイルがあってCSVの値だけ
> 上書きで保存したいと考えているのですが、可能なのでしょうか?
これは、
あるテキストファイルの内容を、Excelの2行目以降に貼り付けた後で、
その2行目以降の内容を、別の(既存の)テキストファイルにCSV形式で保存したい。
という事でしょうか。それとも、
あるテキストファイルの内容を、既存*.xlsファイル上のワークシートの
2行目以降に、貼り込みたい。この時に、ワークシート上にあるデータは
無視して、上書きされるようにしたい。
という事でしょうか。(それとも…?)
前者であれば、
案1: Openステートメントでテキストファイルを開き、自前でCSVを作成。
案2: データだけを新規ワークシートに複写しておき、そのシートだけを
SaveAsメソッドで、Excel形式のCSVファイルとして保存する。
などといった方法が考えられます。
後者であれば、やはりQueryTableを使うのが楽でしょう。
あらかじめ、xls上の特定位置にQueryTableを定義しておけば、
簡単にデータを更新させる事ができます。
QueryTableは、ワークシートに外部データ(例えばテキストファイル)を
貼り込むためのメソッドです。この場合、新規のワークシートを作成して、
そこに読み込ませるようにする事もできますし、既存のワークシートの
特定位置(例えば2行目…すなわち、A2セルから)に貼り込む事もできます。
(Excelでいえば、[データ]-[外部データの取り込み]-[データの取り込み]に相当)
もちろん、『システムの仕様上、QueryTableでは都合が悪い』などという理由があれば、
OpenTextを使って、先述したような方法で処理するのも一つの手かと思います。
魔界の仮面弁士様
本当に感謝しております。いつもありがとうございます。
まず、QueryTableを使用させていただき、データのはりつけを
行ったのですが、カンマを含めて1つの列に張り付いてしまっています。
カンマ毎にセルを変更するなんてことも出来るのでしょうか?
形式ですが、CSV形式のデータを開き、Excel形式で保存したいと考えています。
それから、データのはりつけなのですが、既存のシートに罫線を引いてあって
罫線を残したまま、そこに値だけを貼り付けるようにしたいと考えています。
[編集]→[コピー] [編集]→[形式を選択してはりつけ]→[値]
みたいなものを想定していたのですが・・・
2行目からというのは、1行目には予め隠しでデータが入っているため、消すことも出来ないようになっています。そのため、既存のシートの2行目から
データを貼り付けたいのです。
やはり、地道にCSVをOpenで開いた後、セルに埋め込んでいくしか
ないのでしょうか?
いつも質問ばかりで申し訳ないですが、よろしくお願いいたします。
> カンマ毎にセルを変更するなんてことも出来るのでしょうか?
TextFileCommaDelimiterプロパティを指定してください。
QueryTableには、数多くのプロパティが用意されており、それらを使うと、
そこそこ細かい設定もできるようになっています。
> [編集]→[コピー] [編集]→[形式を選択してはりつけ]→[値]
> みたいなものを想定していたのですが・・・
? ならば、そのようなコードを書けば良いだけなのでは。
その方法で良いならば、先の回答で
》 OpenTextした後に、その内容を別のシートの2行目以降にCopyする事になるかと。
とも書いたように、OpenText()で読み込ませても十分ですよね。
> やはり、地道にCSVをOpenで開いた後、セルに埋め込んでいくしか
> ないのでしょうか?
例えば、そのCSVファイルを ADODB.Recordsetに読み込ませておき、
objSheet.Range("A2").CopyFromRecordset objRecordset
とする方法もありますよ。
魔界の仮面弁士様
様々なお答え、誠にありがとうございました。感謝しております。
これからも何かありましたらよろしくお願いいたします。
ツイート | ![]() |