[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『オートシェイプのテキスト編集中』(ところ)
Excelシート上にユーザーフォームを.Show vbModelessで表示したまま、 シート上を操作するプログラムを組んでいますが、シート上のオートシェイプに テキストがあり、このテキストを編集中には、ユーザーフォームのボタンが受け 付けられません。 ESCキーを押す、または、セルをクリックすれば良いのですが、これらの操作を せずにユーザーフォームのボタンをクリック出来る、他に良い方法はないでしょうか? 宜しくお願い致します。
オブジェクトのテキスト編集中はマクロは動作しません。 イベントも起動しないのでMouse_Moveイベントすら使えません。
なので、逆にシェイプに文字を入れる事をVBAで制御してはどうでしょうか?
たとえば Sub SetText() ActiveSheet.DrawingObjects(Application.Caller).Text = InputBox("入力") End Sub こんなコードを標準モジュールに入れておいて シェイプにマクロ登録で上のプロシージャを登録します。
その状態でModelessのフォームを起動した状態でシェイプをクリックすると InputBoxで文字が入力できますし、確実にInputBoxを終了させられるので フォームもそのまま使えると思います。
こんな代替案はいかがですか? (momo)
一例ですが、APIのGetCursorPosを使ってカーソル位置を監視する方法です。 新規ブックにて試してください。
ユーザーフォームを一つ作成してください(UserForm1) UserForm1には、コマンドボタンを二つ用意して下さい。
CommandButton1 ------ テキストボックス編集中にクリックするボタン CommandButton2 ------ テキストボックス作成し、テキストの編集を行う
UserForm1のモジュールに
'============================================================================== Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Declare Function SetCursorPos Lib "USER32" (ByVal x As Long, ByVal y As Long) As Long Private Declare Function GetCursorPos Lib "USER32" (lpPoint As POINTAPI) As Long Private Type POINTAPI x As Long y As Long End Type '=============================================================================== Private Sub CommandButton1_Click() MsgBox "コマンドボタンが押せました" End Sub '=============================================================================== Private Sub CommandButton2_Click() SetCursorPos ActiveCell.Left * 96 / 72 - 5, ActiveCell.Top * 96 / 72 - 5 Me.Left = ActiveCell.Left + ActiveWindow.PointsToScreenPixelsX(0) * 72 / 96 + 30 Me.Top = ActiveCell.Top + ActiveWindow.PointsToScreenPixelsY(0) * 72 / 96 + 30 mk_textbox End Sub '=============================================================================== Sub mk_textbox() Dim vLeft, vtop, vHeight, vWidth As Long Dim txt As String Dim svx As Double, svy As Double Dim Poi As POINTAPI AppActivate Application.Caption DoEvents With ActiveCell '位置調整 vLeft = .Left vtop = .Top vHeight = .Height vWidth = .Width End With With ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, vLeft, vtop, vWidth, vHeight) .Fill.ForeColor.RGB = RGB(255, 204, 204) With .TextFrame With .Characters .Text = "" With .Font .Name = "MS Pゴシック" .Size = 8 End With
End With End With .Select SendKeys " {BS}" On Error Resume Next Do While Selection.Name = .Name If Err.Number <> 0 Then Exit Do Call GetCursorPos(Poi) With UserForm1 If Poi.x * 72 / 96 >= .Left And Poi.y * 72 / 96 >= .Top Then If Poi.x * 72 / 96 <= .Left + .Width And Poi.y * 72 / 96 <= .Top + .Height Then ActiveCell.Activate Exit Do End If End If End With DoEvents Sleep 100 Loop On Error GoTo 0 .TextFrame.AutoSize = True End With End Sub
標準モジュールに Sub test() UserForm1.Show vbModeless End Sub
testを実行してみてください。
UserForm1が表示されます。 CommandButton2をクリックしてみてください。 アクティブセル付近にテキストボックスが作成され、テキスト編集状態になっています。 適当にテキストを入力してください。編集終了後、直接CommanduButton1をクリックしてみてください。 マウスカーソルがUserForm1の領域に入ると、テキスト編集が終了するので、 CommanduButton1のクリックが可能になります。
これは、あくまでも一例です。簡単なAPIなのでこれらを工夫して、もっと他に良い仕様が 思いつけばよいのですが・・・・。
ユーザーフォームのモーダレスでの運用はいろいろな意味で難しいですね!! だからって、上記をモーダルにして、全部VBAでやってしまおうとすると、これもまた大変だしね!!
何かの参考になれば・・・・。
ichinose
momoさんありがとうございます。 試してみましたら、確かに便利です。 ただ通常の編集にも入れるので、完璧とまでいきませんでした。 編集に入りたいは、ある時は入れなくていいわでちょっと 条件がごちゃになってます。ので ほかに方法が見つからなければ、これが最適になりそうです。
ichinoseさんありがとうございます。 まだ試せてませんので、あとでご報告させていただきます。 (ところ)
条件によっては色々可能ですけどね。
たとえば、UserForm1が表示されている時だけシェイプの編集を可能にするなら
Sub SetText() If UserForm1.Visible = True Then ActiveSheet.DrawingObjects(Application.Caller).Text = InputBox("入力") End If End Sub
こんな風に判定してあげればいいですし。
(momo)
ichinoseさん大変お世話になります。 拝見させていただきました。 SendKeys " {BS}" で 書き込み出来ません。 とエラーします。 わからないので、コメントアウトして動かしてみましたら、動作概要はわかりました。
自分で変更何とかならないかと少し試しましたが、とても変更出来るレベルではありませんでした。 そこで大変申し訳ないのですが、こんな仕様で作っていただくわけにはいきませんか?
・オートシェイプは既に複数作成されている状態でこれらを編集します。 ・いずれかのオートシェイプを編集している時に、ユーザーフォームにカーソルが行くと編集モードから抜けたい。 (出来ればescキーを送信するイメージ)オートシェイプは、文字編集出来ても、サイズが変更出来なくロックされているものも存在するから。 ・オートシェイプの文字編集のタイミングは、ありませんが、もしタイミングが必要であれば、ユーザーフォームにボタン追加等してもいいです。
(ところ)
momoさんので確かにいけそうなのですが、ちょっと変な事情があるんです。 こちらを先に話すべきだったと反省してます。 ・とても大きいイメージファイルが張り付いていて、その上に、テキストの書き込める、オートシェイプがいくつも乗っています。 ・このオートシェイプは、文字のみ書き込める様にロックされています。 つまりこのファイルに文字のみ書き込む人は、escキーを押さない限り文字編集モードから抜けられない。 セルは、セレクト出来なくしてます。セレクト出来る様にしたとしても、下絵のイメージファイルが大きすぎて選択に面倒です。 (だったらescキーを押す様に促すだけでいいだろと言われそうですが)
また、 上記のファイルには、マクロは一切入っていませんが、このファイルを作るエクセルブックが別にありまして、このブックの操作をしている最中にも オートシェイプの編集モードから抜けだしにくいと言う問題があります。 さらにこのブックを触っている時は、オートシェイプの文字フォントとかも触るので とか、いろいろありまして。 (だったらescキーを押す様に促すだけでいいだろと言われそうですが) escキーを押すと言うこともわかりにくいと言われてまして。 こんな感じの状況です。 (ところ)
フォントなども変更するのですか・・・ 文字だけなら、たとえばテキスト部分だけをコントロールのラベルなんかを使って MouseMoveイベントやMouseUpイベントでInputBoxで入力させる。なんて事をすれば マクロの動作を止めずに出来るかな〜とか思ってみたのですが、お役に立てずすみません。 (momo)
>SendKeys " {BS}" >で 書き込み出来ません。 とエラーします。 何でだろう? excel2002では、正常に作動していますけどね!!
ちょっと仕様を変えます。
新規ブックにて、以下の標準モジュールのsample_autoshapeを実行し、サンプル的なオートシェイプを作成します。
sample_autoshapeにて作成されたオートシェイプには、select_shpというマクロを登録してあります。
'=============================================================================== Sub sample_autoshape() With ActiveSheet With .Shapes.AddShape(msoShapeRectangle, 114#, 89.25, 142.5, 39.75) .OnAction = "select_shp" End With With .Shapes.AddShape(msoShapeOval, 369#, 78#, 129.75, 41.25) .OnAction = "select_shp" End With With .Shapes.AddShape(msoShapeExplosion2, 378.75, 183#, 221.25, 57.75) .OnAction = "select_shp" End With End With End Sub '==================================================================================== Sub select_shp() ActiveSheet.Shapes(Application.Caller).Select End Sub
これでサンプルオートシェイプが作成できました。
次にユーザーフォームを一つ作成してください(UserForm1) UserForm1には、コマンドボタンとラベルをひとつずつ作成してください。
CommandButton1 ------ テキストボックス編集中にクリックするボタン テスト用 Label1 ------ 選択されたオートシェイプの名前がを選択中は表示する
では、コードです。
クラスモジュールを作成してください(Class1)。
'========================================================================== Option Explicit Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Event selectshape(obj As Shape) Public kanshi As Boolean 'true 監視中 false 監視中止 Sub exec_kanshi(typ As MsoShapeType) 'Shapeオブジェクトの選択を監視する kanshi = True Dim obj As Object Dim shps As ShapeRange On Error Resume Next Do While kanshi Err.Clear Set obj = Selection Set shps = obj.ShapeRange If Err.Number = 0 Then If shps.Count = 1 Then If shps(1).Type = typ Then RaiseEvent selectshape(shps(1)) 'イベント End If End If End If Sleep 10 DoEvents Loop End Sub
次にUserForm1のモジュール
'============================================================================= Option Explicit Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Declare Function SetCursorPos Lib "USER32" (ByVal x As Long, ByVal y As Long) As Long Private Declare Function GetCursorPos Lib "USER32" (lpPoint As POINTAPI) As Long Private Type POINTAPI x As Long y As Long End Type Private WithEvents kanshi As Class1 Private Sub CommandButton1_Click() 'テスト用ボタン MsgBox "ボタン1が押された" End Sub '============================================================================= Private Sub kanshi_selectshape(obj As Shape) Dim Poi As POINTAPI On Error Resume Next Label1.Caption = "オートシェイプ " & obj.Name & " 編集中です" Do While Selection.Name = obj.Name If Err.Number <> 0 Then Exit Do Call GetCursorPos(Poi) With Me If Poi.x * 72 / 96 >= .Left And Poi.y * 72 / 96 >= .Top Then If Poi.x * 72 / 96 <= .Left + .Width And Poi.y * 72 / 96 <= .Top + .Height Then ActiveCell.Activate End If End If End With DoEvents Sleep 100 Loop Label1.Caption = "" On Error GoTo 0 End Sub '============================================================================= Private Sub UserForm_activate() Set kanshi = New Class1 kanshi.exec_kanshi msoAutoShape 'オートシェイプの選択を監視 End Sub '============================================================================= Private Sub UserForm_Terminate() kanshi.kanshi = False '監視終了 End Sub
最後に標準モジュール(Module2)に
'============================================================================= Sub test() UserForm1.Show vbModeless End Sub
一度保存して閉じてから、再度開いて試してください。
予め作成されているオートシェイプがあるシートをアクティブにして、testを実行してください。
UserForm1がモードレスモードで表示されます。 編集したいオートシェイプを選択してください。 選択が成功すると、Userform1のラベルに選択中のオートシェイプの名前が表示されます。 但し、通常の図形選択と違い、選択していることがわかりづらいです(そのためにラベルに表示しました)
右クリックメニューを使って、テキスト編集を行ってください。編集途中でUserform1のボタンをクリックしてください。
ボタンがクリック可能になっています。
他の機能(文字の大きさなど)も使えますから試してみてください。
ichinose
ichinoseさん動かしてみました。 希望通りに動作致しました。大変有り難う御座います。 確かにおっしゃる通り図形には、編集中がわかりにくいですが、ラベルを強調 表示することでしっかりわかります。 大変お世話になりました。 momoさんも大変有り難う御座いました。 (ところ)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.