[[20230621134314]] 『文字列クリップボード格納で文字化け』(ウルトラの孫) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『文字列クリップボード格納で文字化け』(ウルトラの孫)

 文字列をクリップボードに格納するコードを作成中です。
 下記のコードは簡単なテスト用です。
 文字列をクリップボードに格納するFunctionを二通り
 テストしています。
 cbsetBの方はtestのcbstrA、cbstrB両方ともきちん
 と格納できます。
 しかし、cbsetAの方はtestのcbstrBはきちんと格納
 できますが、cbstrAの方は文字化けしたものがクリップ
 ボードに格納されてしまいます。

 CreateObject("Wscript.Shell").Exec("clip").StdIn.Write〜
 は、何かしらの制約があるのでしょうか?
 ネット検索しても制約があるような記述は見つけられませんでした。

 文字数に制約があるのかな、と思い、文字を削ったりしましたが、
 文字数より文字列の内容か文字の組み合わせによるような気も
 します。
 何かお気づきの方、ご教示お願いします。

 Sub test()
  Dim cbstr As String
   cbstrA = "1234(定期点検用点検整備記録簿)"
   'cbstrB = "1234(定期点検用点検整備記録)"
   Call cbsetA(cbstrA)
   'Call cbsetB(cbstrA)
 End Sub

 Function cbsetA(ByVal cbstr As String)
  CreateObject("Wscript.Shell").Exec("clip").StdIn.Write (cbstr)
 End Function

 Function cbsetB(ByVal cbstr As String)
  Dim doA As MSForms.DataObject
   Set doA = New MSForms.DataObject
   doA.Clear
   doA.SetText Text:=cbstr
   doA.PutInClipboard
 End Function

< 使用 Excel:Excel2007、使用 OS:Windows10 >


 CreateObject("Wscript.Shell").Exec("clip").StdIn.Write cbstr & vbLf
 とか 
 CreateObject("Wscript.Shell").Exec("clip").StdIn.WriteLine cbstr
 とか
 CreateObject("Wscript.Shell").Exec "cmd.exe /c echo " & cbstr & " |clip"
 とか
 でうまくいくみたいです
(´・ω・`) 2023/06/21(水) 14:23:46

 こうするとウインドウが表示されないので、個人的にはこっちが好きかも

 Sub test()
   Dim cbstrA As String
   cbstrA = "1234(定期点検用点検整備記録簿)"
   cbsetA cbstrA
 End Sub

 Sub cbsetA(ByVal cbstr As String)
   CreateObject("Wscript.Shell").Run "cmd.exe /c echo " & cbstr & " |clip", 0, True
 End Sub
(´・ω・`) 2023/06/21(水) 14:54:12

 (´・ω・`)さん、ご教示ありがとうございます。

 >CreateObject("Wscript.Shell").Exec("clip").StdIn.Write cbstr & vbLf
 >CreateObject("Wscript.Shell").Exec "cmd.exe /c echo " & cbstr & " |clip"

 この二つは文字化けしませんでしたが、最後尾に改行が付いてしまいます。

 >CreateObject("Wscript.Shell").Exec("clip").StdIn.WriteLine cbstr

 このコードは、文字化けしてしまいました。

 文字列をクリップボードに格納する方法はたくさんあるので目的としては解決している
 のですが、出来たら原因を究明したいと思います。

 回避方法が内容でしたら使用を諦めます。
(ウルトラの孫) 2023/06/21(水) 15:56:55

 CreateObject("Wscript.Shell").Exec("clip").StdIn.Write cbstr & vbLf
 は 
 CreateObject("Wscript.Shell").Exec("clip").StdIn.Write cbstr & vbCrLf
 じゃないとダメみたい
 文字のバイト区切りがうまくとれてないみたいなので、
 文字列の終端を示すコードを入れてやればいいと思うのですが、
 なにがいいのでしょうね?
(´・ω・`) 2023/06/21(水) 16:16:12

 vbNullCharでイケませんかね?
(白茶) 2023/06/21(水) 16:28:19

 >vbNullChar
 だめでした。ASCIIコード表のそれっぽいのはほとんど試しましたがダメでした

 コマンドラインでClipコマンドにファイルを食わせてみたら、
 改行コード(CRLF)がないと文字数によって化けるので、
 Clipコマンド自体の仕様のような気がします。
(´・ω・`) 2023/06/21(水) 16:40:16

 あー、ダメでしたか... ^^;

(白茶) 2023/06/21(水) 16:42:28


 >コマンドラインでClipコマンドにファイルを食わせてみたら、
 >改行コード(CRLF)がないと文字数によって化けるので、

 コマンドライン上の話ですが、コードページをUnicode(UTF-8)にして(CHCP 65001)、
 Unicodeのファイルを標準入力から食わせてやると改行コードがなくても大丈夫でした(たぶん)

 Wscript.Shell をコードページをUnicodeにして起動して、
 文字列を StrConv(cbstr,vbUnicode)して送り込めばいいんじゃないかと思いつつ、

 >Wscript.Shell をコードページをUnicodeにして起動
 どうしたら????
(´・ω・`) 2023/06/21(水) 17:05:15

 わたしはあきらめました
 別案は最初からでてますし
 というわけで撤退します

 clipコマンドよりpowershellのset-clipboardのほうが良さげなんですが
 なんかこれはこれで、、、
(´・ω・`) 2023/06/21(水) 18:06:20

 (´・ω・`)さん、白茶さん、いろいろご検討ありがとうございます。

 スキャナから自動で現在日時のファイル名が付されて吐き出されたPDFファイルを手動で開いて中身を確認して
 車のナンバー+(車検/自動車検査証記録事項/定期点検用点検整備記録簿/2年定期点検用点検整備記録簿/自賠)
 でリネームする作業をある程度自動化するツールを作り始めました。
 TextBoxに車番、ListBoxで車検等を選択して文字列を結合したものをクリップボードに格納して、F2キーでファイル名を
 選択状態にしてファイル名のところにCtrl+Vでクリップボードの内容を貼り付ける、というものです。
 作成途中で文字化けに気が付きご相談した、というわけです。
 ユーザーフォームを使ってますので参照設定を手動でしなくてもcbsetBが使えますので面倒はないのですが、クリップボード
 格納の方法をいくつか試した中で文字化けが起きた、という具合です。

 まだ作成途中ですが、ListViewにファイルをドラッグ&ドロップしてFileSystemObjectを使用してリネーム、という方向へ
 方針転換しました。

 お騒がせした挙句全然違う方法で申し訳ありませんが、質問事項の方法での解決は諦めました。
 ご教示いただきありがとうございました。
(ウルトラの孫) 2023/06/21(水) 19:00:07

 クリップボード関係だとAPI使ったやり方も候補のひとつではありましょう。
 これも割と王道的手法だと思ってます。(個人的には ^^;)

    Option Explicit
    Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hWnd As LongPtr) As Long
    Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long
    Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
    Private Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr
    Private Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As LongPtr) As LongPtr
    Private Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
    Private Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As Long
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As LongPtr)
    Private Const GMEM_MOVEABLE As Long = &H2
    Private Const GMEM_ZEROINIT As Long = &H40
    Private Const GHND          As Long = (GMEM_MOVEABLE Or GMEM_ZEROINIT)
    Private Const CF_UNICODETEXT As Long = &HD
    Sub SetClipboard(str As String)
        Dim h As LongPtr, p As LongPtr
        If OpenClipboard(0) <> 0 Then
            If EmptyClipboard() <> 0 Then
                h = GlobalAlloc(GHND, LenB(str) + 2&)
                p = GlobalLock(h)
                CopyMemory ByVal p, ByVal StrPtr(str), LenB(str)
                Call GlobalUnlock(h)
                Call SetClipboardData(CF_UNICODETEXT, h)
                Call CloseClipboard
            End If
        End If
    End Sub

    Sub Test()
        SetClipboard "1234(定期点検用点検整備記録簿) / 56" & ChrW(8467)  & " 78" & ChrW(13137)
    End Sub

 (参考文献)
64bit VBAでクリップボードに文字列を設定・取得 - Qiita
https://qiita.com/7shi/items/61f4c4e132835b26b3ea

(白茶) 2023/06/21(水) 19:05:01


 白茶さん、追加回答ありがとうございます。

 32bit版を試したらうまくいきました。
 ありがとうございました。

 また、↓も試してみました。こちらは一時的にコントロールを追加してますのであまり
 使いたくはないですが・・・。

 クリップボード格納の方法はいろいろありますのでいろいろ試してみたいと思います。
 ありがとうございました。

 '★参照設定
 'Microsoft ActiveX Data Object

 Sub test2()
  Dim mytb As OLEObject
  Dim ws As Worksheet
  Dim cbstr As String
   cbstr = "1234(定期点検用点検整備記録簿)"
   Set ws = ActiveSheet
   Set mytb = ws.OLEObjects.Add(ClassType:="Forms.TextBox.1", Link:=False, _
    DisplayAsIcon:=False, Left:=0, Top:=0, Width:=1, Height:=1)
   With ws.OLEObjects(mytb.Name).Object
    .MultiLine = True
    .Value = cbstr
    .selstart = 0
    .SelLength = Len(.Value)
    .Copy
   End With
   mytb.Delete
   Set mytb = Nothing
   Set ws = Nothing
 End Sub
(ウルトラの孫) 2023/06/21(水) 19:29:09

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.