
Excel VBAを使っていて
512×512の二次元配列をクリップボードにコピーして
シート上でペーストすることでシートに貼り付けられるようにしたいのですが
どうすれば良いですか?
https://oshiete.goo.ne.jp/qa/5650002.html
検索すると単一の変数のクリップボードへの転送方法に関しては
このページなどにたくさん見つかるのですが
配列を転送方法について書かれたページが見つかりませんでした。
とりあえず、
Open filepath3 For Output As #1
でタブ区切りのファイルとして一時保存した後に
.SetText FSO.GetFile(filepath3).OpenAsTextStream.ReadAll
.PutInClipboard
Readallで読み込むことで所望の操作を行うことができました。
しかし、HDDに一時ファイルを生成せずに
直接配列からクリップボードにコピーする方法があれば教えてください。
さんざん検索しても分かりませんでした。
No.1ベストアンサー
- 回答日時:
こんにちは。
おやおや回答しようとしたら削除されてましたね。
せっかく書いていたので、少しの加筆だけで投稿します。
(少々文脈が乱れますがご容赦)
> Excel VBAを使っていて
> 512×512の二次元配列をクリップボードにコピーして
> シート上でペーストすることでシートに貼り付けられるようにしたいのですが
> どうすれば良いですか?
ちょっとこれだけでは何とも答え難いですが、
https://oshiete.goo.ne.jp/qa/8944391.html
でのご質問の延長、ということでしたら、
hairetuが取得出来ているとして、
' ' ///
Dim nYSize As Long, nXSize As Long
nYSize = UBound(hairetu) - LBound(hairetu) + 1
nXSize = UBound(hairetu, 2) - LBound(hairetu, 2) + 1
' ' 以下、セル範囲への出力(B2を左上にして512*512のセル範囲)
Cells(2, 2).Resize(nYSize, nXSize).Value = hairetu
' ' ///
のように、そのまんま配列をセル範囲に出力すればいいのでは?
出力先のセル範囲に既存のデータがある場合は、一旦、
range.ClearContents で空にしてから出力した方が
遅くなる原因を減らして速くなる場合が多いです。
その他、セル範囲への出力の際の定番、
Application.ScreenUpdating = False ' 描画更新停止
' ' セル範囲への出力処理
Application.ScreenUpdating = True
とか、
Application.Calculation = xlCalculationManual ' 再計算停止
' ' セル範囲への出力処理
Application.Calculation = xlCalculationAutomatic
とか、
Application.EnableEvents = False ' イベント停止
' ' セル範囲への出力処理
Application.EnableEvents = True
など、必要に応じて書き加えます。
二次元配列変数の値をセル範囲へ出力するだけなら、
上記の方法は一般的、です。
ただ、バイナリをそのままセル範囲に出力、というのは、
私個人は実験以外に経験ないので、もし勘違いでもあればすみません。
前スレの、、、
> ワークシートのセルの内容をタブ区切りのテキストデータとして出力するプログラム
上記の方法でセル範囲への出力が出来たとして、
' ' ///
range.Copy ' ←セル範囲を指定すること
Dim oDTO As MSForms.DataObject
Set oDTO = New MSForms.DataObject
oDTO.GetFromClipboard
sBuf = oDTO.GetText
Set oDTO = Nothing
' ' ///
のようにします。
hairetuが取得出来ているなら、
最初に提示した方法でそのままセル範囲に出力して、続けて
この方法でタブ区切りのテキストにすることも出来るということです。
タブ区切りのテキストさえ出来てしまえば、
Open filename For Output As #
とか、色んな方法で出力できますね。
さて、
DataObject .SetText .PutInClipboard の組合わせを
用いる利点があるとすれば、
Excelシートのデータを整形して外部アプリケーションに送る時や、
HTML/XMLテーブルをソースから直接読込んでExcelシートに貼り付ける時、
とかに限定されるように思います。
データベーステーブルの体裁を持ったファイルなら、adodb経由で
adodb.recordset.GetRows とか、
adodb.recordset.GetString とか、
excel.range.CopyFromRecordset みたいな、
用途に見合った形の配列の扱い方が用意されている場合もあります。
部分的な手法に目を向けるよりも、やろうとしている処理内容を
基準に調べた方が吉、という場合もあるのかもしれませんね。
でも、申し訳ないけど、全体として何をやりたいのか解りませんし、
私がどこまで役に立てるかもわかりませんから、
直接にはあまり示唆的なことを書けないような気がします。。
> 配列を転送方法について書かれたページが見つかりませんでしたので
> どうか教えてください。
> しかし、HDDに一時ファイルを生成せずに
> 直接配列からクリップボードにコピーする方法があれば教えてください。
結論としては、配列変数の値を直接的にクリップボードに送るような方法は
用意されていません。
(APIとか.NetFrameWorkとか使えば出来るのかも?ですが私の守備範囲外ですし、
出来たとしても「直接」とは言い難いし、そこまでする必要もなさそうと判断しています。)
期待通りのものではないでしょうけれど、
普通に文字列処理をするだけのベタな方法です。
速さを意識するのなら、
現行のExcelでは、[貼付け]に要する時間が大きめなので、
期待外れに終るような気もします。
っていうか、本当にこのプロセスが必要だとは思っていないのです。
最初に書いたGetFromClipboardまでの処理の流れの方を
薦めているつもりですが、ココでは一応お求めのまま。
' ' /// ダミー配列変数の値をタブ区切りCrLf改行のプレーンテキストとしてクリップボードへ出力 ///
Dim sTempLine As String
Dim sBuf As String
Dim i As Long, j As Long
For i = 1 To nYSize
sTempLine = ""
For j = 1 To 512
sTempLine = sTempLine & vbTab & hairetu(i, j)
Next j
sBuf = sBuf & vbCrLf & Mid$(sTempLine, 2)
Next i
sBuf = Mid$(sBuf, 3) ' タブ区切りテキスト作成完了
Dim oDTO As MSForms.DataObject
Set oDTO = New MSForms.DataObject
oDTO.SetText sBuf, 1
oDTO.PutInClipboard ' タブ区切りテキストをクリップボードへ出力
Set oDTO = Nothing
' Cells(2, 2).PasteSpecial
' ' ///
再度、
> しかし、HDDに一時ファイルを生成せずに
抵抗感があるのは何となく理解できますけれど、
上級者さんの感覚では、ただ単にHDDのメモリを借用するだけ、
どこのメモリを使うかの違いだけ、なのかも、です。
ファイル操作処理に限らず、メモリを大量に食うような処理では、
tempファイルを使うことは一般的なことですし、
必要以上に難しく考えなくてもいいのかな、とは思います。
ただ、今回の設問の限りでは、そこまでの必要はない、ですね。
とりあえず、以上です。
お訊ねの内容と、関連した私の解答に関する補足質問にはお応えします。
No.2
- 回答日時:
こんにちは。
前回のやりとりから読んでいました。失礼かもしれませんが、そんなに高度の話ではなさそうなのに、さっぱり、意図が分からずじまいで、そのやりとりの取っ掛かりさえ見当つきませんでした。私のマクロをみて、ローテクしかないと、揶揄する方もいるかもしれませんが、いくつかの疑問点を、もう少し状況を教えていただけませんか?だから、私などお話にならないとお思いでしたら、無視なさっても結構です。
なお、クリップボードに入れるワザとしては、この私でさえ、いくつか知っておりますが、ただ、どれもExcelにしろオブジェクトを使う作業過程で、オブジェクトの実体化の実質的な時間を加味すれば、[512*512]程度のファイルでは、よほどのことがない限りは、その差は大きくないはずです。1秒が1時間のように感じるなら別ですが。某氏が別の掲示板で、「(マクロの)実行は3秒、その開発は3日。」けだし名言です。
疑問点として
・バイナリデータとお書きになっていたけれど、
「二次元配列データが入ったバイナリデータを読み込んで」
まさか、バイナリファイルでもないでしょうし、バイナリデータを他に変換しているわけでもないはずです。その最初の取っ掛かりの部分が明らかになっていないように思います。こちらは、0から255までの数値の入った[512 * 512]のデータを想定しています。ここらが、最初のモヤモヤの発端です。
・タブ区切りのファイルとして一時保存
[512 * 512]のファイルを出力するなど、インポートも、エクスポートも、一瞬に近いはずです。それを入れ出しするというものなのでしょうか。CSVであろうが、TSVであろうが、あまり問題はないと思います。
それに、インポート方法もいろいろあるはずです。[512 * 512]のデータのインポートなど、それほどに時間が掛かるはずもないし、テンポラリーファイルの何が問題なのかも不明です。加工があるというなら別ですが。
・HDDに一時ファイルを生成せずに直接配列からクリップボードにコピーする方法
仮に、テンポラリファイルであろうが、ファイル自体は存在しているし、クリップボードに格納する場合は、そのファイル自体を、クリップボードのとば口に持ってこなくてはいけなくてはいません。VBA等で、名指しでファイルに命令して、そんなに手間が掛かるとは思えません。
[オブジェクト生成](一部はの方法は、OS側が保持、しかし、命令手順が必要]
「クリップボード・オブジェクト」<- データ [インポート]
[物理的移動]
[命令]-[ペーストのオブジェクトを確保]
「クリップボード・オブジェクト」->- データ [エクスポート]
このような手間を考えるなら、Excelへのインポートは、QueryTableひとつで十分だと思います。
Test1.txt (TSVファイル) サイズ 約1M 弱
出力はいうまでもありません。シートコピー・保存で十分です。(後に、多少の違いは見つかりました)
計測データ(timeGetTimeによる)
Import: 488 /1000 sec (以下 1000 secは省略)
Emport: 456
二度目
EmportFile: 486
ImportFile: 540
'//
Sub ImportFile()
Dim Fname As String
Dim objQT As QueryTable
Fname = "TEXT;" & ThisWorkbook.Path & "\Test1.txt"
Set objQT = ActiveSheet.QueryTables.Add(Fname, Range("A1"))
With objQT
.Name = "Test1"
.TextFilePlatform = xlWindows '2
.TextFileColumnDataTypes = Array(1)
.Refresh BackgroundQuery:=False
End With
objQT.Delete
End Sub
'//
Sub ExportFile() '※
Dim myPath As String
myPath = ThisWorkbook.Path & "\"
ActiveSheet.Copy
With ActiveWorkbook
.SaveAs myPath & "Test2.Txt", xlText
.Close False
End With
End Sub
'//
※再計算(Calculate)の他、Event についても注意が必要。割り込みさせられないようにする)
以下のような事は不要だと思います。
しかし、時間を計測すると、QueryTableの10分の1ぐらい速いけれど、これを判別するのは神の領域ではないでしょうか。
ClipBoardTest1: 62
'//
Sub ClipBoardTest1()
'VBEditor 画面は必ず閉じてください。
Dim Filename As String
Dim buf 'Stringにはしないこと
Filename = ThisWorkbook.Path & "\" & "Test1.txt"
Set obj = CreateObject("HTMLfile")
With CreateObject("Scripting.FileSystemObject").OpenTextFile(Filename)
buf = .ReadAll
.Close
End With
obj.parentWindow.clipboardData.SetData "text", buf
Range("A1").Select
Application.SendKeys "^v"
End Sub
ご回答ありがとうございます。
>512*512]程度のファイルでは、よほどのことがない限りは、その差は大きくないはずです。
実行回数が一回なら大差ないですが
1万回ループでこなすのならどうですか?
また一回実行して終わりではなく、何回も何回もパラメータを変えながら
実行しないといけないとなると、少しでも短くしたくなるでしょ?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(Microsoft Office) マクロVBAについて 1 2022/09/06 18:12
- Visual Basic(VBA) エクセルのマクロについて教えてください。 4 2023/05/24 08:33
- Visual Basic(VBA) 改行ごとに行を追加し、数量を分割 4 2023/07/11 16:39
- Excel(エクセル) 【困っています】VBA 追加処理の記述を教えてください。 1 2022/08/25 22:54
- Visual Basic(VBA) エクセルのマクロについて教えてください。 1 2023/08/03 11:27
- JavaScript javascriptのちょっとした動作不良(原因は突き止めたのですが) 1 2023/06/15 19:58
- Excel(エクセル) シートが違う2枚のエクセルシートにある数値を別シートにコピーしたい(VBA?) 8 2022/03/31 12:24
- Visual Basic(VBA) まとめシートから集計シートへA列のコードが一致したら1行コピーするマクロをネット上で見つけました。こ 1 2022/08/30 14:11
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Excel(エクセル) エクセルのマクロについて教えてください。 3 2023/02/07 14:47
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
パイプで標準出力を隣のコマン...
-
拡張子.vsdをイラストレーター...
-
JSPでエクセル作成
-
ストリームについて
-
Acccess レポートをグループ別...
-
BitBltについて。
-
ADボードのプログラムでの無限...
-
Webアプリケーションの公開にあ...
-
大量のHTMLデータのテキスト、...
-
1行ずつではなくまとめてファイ...
-
I/Oエラー(Delphi)
-
コマンド(例えばls)の出力結果...
-
印刷時のジョブ名
-
Excel VBA ファイル一覧とファ...
-
VBA でメモ帳へ保存する際の保...
-
CSVの出力(1行を3行に出力~)
-
C言語 ドラッグとファイル名の表示
-
VCソース内でJPEGやGIFファイル...
-
半年以上前のファイルの時刻表示
-
シェルコマンドの 2>&1 とはど...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コマンド(例えばls)の出力結果...
-
【ExcelVBA】UTF-8(BOM無)でC...
-
ファイル出力の場所を指定
-
VC++でUTF-8のファイルを出力し...
-
ファイルの文字コードをUTF-8に...
-
シェルコマンドの 2>&1 とはど...
-
Acccess レポートをグループ別...
-
BitBltについて。
-
Wordマクロで指定したフォルダ...
-
ファイル形式またはファイル拡...
-
CSV形式に変換
-
テキストファイルに改行コード...
-
C++ fprintf_sの使い方がわからん
-
外国語とCSVについて
-
1行ずつではなくまとめてファイ...
-
pcap形式データをテキストへ抽出
-
重複チェックプログラム
-
AviUtlでAVI出力が途中までしか...
-
CBool関数について VB6とVB.net...
-
標準出力とファイルに効率的に...
おすすめ情報