- ベストアンサー
クリップボードの値を求める
クリップボードに以下の情報がある場合 例題 : (ABCDEDF) aaaaa (bbbbbb) (123456) 789 ああああ (いいいいい) 1行目と2行目の一番左の()内の文字列(又は数値)をVBAで抽出したいのですが どうしたら良いですか? 例題 : では、 ABCDEF と 123456 を抽出 利用環境 Excel2021 (Windows_11)
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
> プライベートレベルの変数で宣言しているのに あっ! VBAは グローバルとかローカルじゃなくて パブリックモジュールレベルやプライベートモジュールレベルやプロシージャレベルが正しいんですね。 今知りましたありがとうございます。 Sub クリップボード有効利用() の中で CM1とCM2の値を見ていたのでしたか。 私は 自動貼り付け() の CM1 = ExtractionStrings(m1) CM2 = Val(ExtractionStrings(m2)) の時点で見てました。 プライベートモジュールレベル変数は使わずに元のプロシージャで宣言して Function 呼び出し時に引数で変数を渡した方がいいのではないかと思います。ただし、前回の再帰の時のようにスタックオーバーフローが出たら仕方がないですが。 いまさらですが前回 GetFileInfoの最後に Set objFile = Nothing が無かったのがもしかしてオーバーフローの原因なのかなと、関係はないような気もしますが今再度見て感じました(そう思うだけで自信はありません)
その他の回答 (5)
- kkkkkm
- ベストアンサー率66% (1734/2604)
For i = 1 To 2 cbin = Split(SrcAry(i - 1), "|") For ii = 0 To UBound(cbin) If i = 1 Then m1 = cbin(1) If i = 2 Then m2 = cbin(0) Next Next For ii = 0 To UBound(cbin)のループが何故あるのか分かりませんが クリップボードの2行分だけm1,m2に"|"で分割して振り分けていますが m1が1行目の2番目の文字列 m2が2行目の1番目の文字列 に振り分けられていると思います。 1行目の2番目の文字列に[]で囲まれた部分がない 2行目の1番目の文字列の先頭に数値以外がある 上記の場合 CM1="" CM2=0 となります。 CM2=0 は Val(ExtractionStrings(m2)) になっているためです。 こんなデータの場合です [1行目1]) | aaaaa 1行目2 [え2行目1] | 789 ああああ [2行目2] [3行目1] | 789 ああああ [3行目3] あと、グローバル変数はいらないと思います。
お礼
kkkkkmさん、アドバイス感謝します。 原因が判りました。 Dim CM1 As String, CM2 As Integer プライベートレベルの変数で宣言しているのに 同じ変数の宣言を「自動貼り付け()」でも行っていました。 (本家とFunctionで2回宣言) ⃣「自動貼り付け()」の方を削除して上手く変数を引き継げるようになりました。 本当にボンミスが多い。 同一モジュールなのでホントは、「宣言セクション」でのプライベートレベルの変数宣言で 無くても良いのですが、私がすぐにどこで使う変数なのかを忘れてしまうので もっと分かりやすい方法(書き方)があるかもしれませんが 覚書のような感じでプライベートレベルの変数にわざわざしています。 (他のプロシージャでも使っているのよ的な....) ⃣ >For ii = 0 To UBound(cbin)のループが何故あるのか分かりません 検討中の残骸が残っていました。 iのみチェックすれば良いのでおっしゃるように必要ありませんでした。 お陰様で何とか基本のコードが出来ました。 エラートラップを付けるなどコード極める方向に進めそうです。 アドバイス感謝いたします。
- imogasi
- ベストアンサー率27% (4737/17069)
既に回答は出ている、が個人的興味がわいて、やって見た。参考になればよいが。 テストのやり方として、 (1)(例えば)メモ帳に ABCDEDF) aaaaa (bbbbbb) 123456) 789 ああああ (いいいいい) 1234) 777 sdfg (1112222) という文字データを作る。 (2)このメモ帳の部分を、操作でコピーする。CTRL+Cなど。 (3)標準モジュールに (注)ツールー参照設定方式を避けたので、下記 Set CB =・・の部分は、(WEBを記事を調べて、真似て)こうなっているが、普通は、参照設定方式でやってください。 ーーー Sub test01() Dim buf As String, buf2 As String, CB As Object Set CB = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") Dim dt As Variant With CB .GetFromClipboard ''クリップボードからDataObjectにデータを取得する buf2 = .GetText ''DataObjectのデータを変数に取得する End With MsgBox buf2 '-----抽出 dt = Split(buf2, vbCrLf) For i = 0 To UBound(dt) MsgBox dt(i) d = Split(dt(i), "(") MsgBox d(1) MsgBox "各行の結果 " & Replace(d(1), ")", "") Next i End Sub を作る。 (もし、何かの拍子に、コピーをするとクリップボードのデータが壊れるので、テストがダメになるので、しばらく実行が終わるまで、注意。) VBAコードを実行する。 「各行の結果」と続いてMsgbox で表示される部分が、求める文字列。 抽出の部分のやり方は、小生が元データの仕様を誤解しているとか、色々あるかも。
お礼
imogasiさん、アドバイスありがとうございます。 何とか、コード作成できそうです。
- kkkkkm
- ベストアンサー率66% (1734/2604)
No.2の追加です。 以前取り出すのをしたことがあったと思ったのですが、一応参考までに。 For i = 0 To UBound(temp) S = InStr(StrConv(temp(i), vbNarrow), "(") E = InStr(StrConv(temp(i), vbNarrow), ")") If S <> 0 And E <> 0 Then Debug.Print Mid(temp(i), S + 1, E - S - 1) End If Next
お礼
kkkkkmさん、今回もお世話になります。 最初の質問と変わって カッコが()では無く[]が対象になりました。 自分でネットにある参考コードを繋ぎ合わせながら 自己流で以下のコードを書きました。 何とか良い方向に進んでいたのですが 初歩的な所で又現在停滞しています。 以下のようなコードで 最初にCM1とCM2を定義して call 自動貼り付け で Functionを呼び出してCM1とCM2を求めています。 ここまでは(Fanction内では)、CM1,CM2 共に問題なく適正な値が求められているのですが Functionを抜けて主コードに帰った時点で CM1、CM2の値が Module1 CM1="" CM2=0 と初期化されてしまいます。 変数の宣言が間違っていると思われますが、 アドバイスをお願いします。 Option Explicit Dim CM1 As String, CM2 As Integer Sub クリップボード有効利用() Call 自動貼り付け (途中のコード省略) Function 自動貼り付け() Dim Src As String Dim SrcAry As Variant Dim DestStr As String Dim i As Long Dim Rw As Long Dim CB As DataObject Set CB = New DataObject CB.GetFromClipboard Src = CB.GetText '行で分割 SrcAry = Split(Src, vbCrLf) Dim cbin As Variant Dim ii As Long Dim m1 As String, m2 As String Dim CM1 As String, CM2 As Integer For i = 1 To 2 cbin = Split(SrcAry(i - 1), "|") For ii = 0 To UBound(cbin) If i = 1 Then m1 = cbin(1) If i = 2 Then m2 = cbin(0) Next Next CM1 = ExtractionStrings(m1) CM2 = Val(ExtractionStrings(m2)) End Function Function ExtractionStrings(rngValue) Dim startNum As Integer, endNum As Integer startNum = InStr(rngValue, "[") endNum = InStr(startNum + 1, rngValue, "]") If startNum <> 0 And endNum <> 0 Then startNum = startNum + 1 ExtractionStrings = Mid(rngValue, startNum, endNum - startNum) Else ExtractionStrings = "" End If End Function
- kkkkkm
- ベストアンサー率66% (1734/2604)
以下のページを参考にしてクリップボードからデータを取得して クリップボードを操作する http://officetanaka.net/excel/vba/tips/tips20.htm 上記でうまくいかない場合は [VBA]DataObjectを使ったクリップボード操作が上手くいかない場合の対処法 https://www.ka-net.org/blog/?p=7537 取得したデータを一行ずつにわけて Dim temp As Variant, i As Long temp = Split(s2, vbCrLf) For i = 0 To UBound(temp) Debug.Print temp(i) Next 取り出したtemp(i)の()間を取り出せばいかがでしょう。
- m5048172715
- ベストアンサー率16% (860/5261)
方針が、 クリップボードの中身を文字列変数に代入、 文字列変数の中身の一部である丸括弧内の文字列を数字にして答えの変数に代入。 だと、なにをどこまで出来ているのだろうか?
補足
>なにをどこまで出来ているのだろうか? 以下で 行で分割までは出来ました。 それ以後コードは思案中なので無視してください。 Sub Sample() Dim Src As String Dim SrcAry As Variant Dim DestStr As String Dim i As Long Dim Rw As Long Dim CB As DataObject Set CB = New DataObject CB.GetFromClipboard Src = CB.GetText '行で分割 SrcAry = Split(Src, vbCrLf) Dim cbin(1 To 2) As Variant Dim ii As Long For i = 1 To 2 cbin(i) = Split(SrcAry(i - 1), "|") If i = 1 Then cbin(i) = cbin(2) If i = 2 Then cbin(i) = cbin(1) MsgBox cbin Next i End Sub
お礼
>プライベートモジュールレベル変数は使わずに元のプロシージャで宣言して > Function 呼び出し時に引数で変数を渡した方がいいのではないかと思います。 そううですね。 そうすれば、変数の引き渡しで迷うことが無さそうです。 と言いながらしばらくすると、忘れてしまって 進歩がない又今回のようなケースが多くなります。 >オーバーフローの原因なのかなと その後思ったのは、変数でbyte等で十分な桁数でも LONGを使った方がメモリーの節約にはなりませんが面倒な事を気にしなくて良さそうなので LONGを使うことにしました。 今回もお世話になりありがとうございました。