[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『Workbook.Save(Close)と手作業での保存(終了)の違い』(てゃ)
Workbook_BeforeSaveにおいてCurrentRegionが正しく取得できない不具合が発生しました。
色々試してみると手作業での保存時には問題ないが、Workbook.Saveを用いると発生することがわかりました。
以下の点について質問させてください。
1. Workbook.SaveからWorkbook_BeforeSaveを呼び出した際にはどのような制限がかかっていますか。
2. この制限を解消する(もしくは手作業での保存と判別する)方法はありますか。
3. Save以外にClose時にも発生していますが、ほかにどのような状況で発生しますか。
また、Workbook.Saveは別のブック(orアドイン)から呼ばれているらしく、
Workbook.Saveを使用しないというのは難しそうです。
よろしくお願いします。
'----不具合再現用のコード------
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
With ActiveSheet .Range("A1").Value = "a" .Range("A2").Value = "b"
Debug.Print .Range("A1").CurrentRegion.Address
End With
End Sub
Sub SaveTest() ThisWorkbook.Save '$A$2ではなく$A$1が表示される End Sub
< 使用 Excel:Excel2016、使用 OS:Windows10 >
Dim msg As String On Error Resume Next With ActiveSheet .Protect Debug.Print .Range("A1").CurrentRegion.Address, 'CurrentRegionプロパティは、保護されたワークシートでは使うことができません。 .Unprotect End With If Err Then msg = "manual" Else msg = "code" End If Debug.Print msg Cancel = True End Sub Sub SaveTest() ThisWorkbook.Save End Sub
(kazuo) 2020/02/19(水) 21:42
With ActiveSheet .Range("A1").Value = "a" .Range("A2").Value = "b" Debug.Print .UsedRange.Address(0, 0, 1, -1) Debug.Print Application.Range(.Range("A1"), _ .Cells(.Rows.Count, "A").End(xlUp)) _ .Address(False, False, xlA1, True) End With End Sub
ん〜〜〜。
なんで、事前にA1とA2になにか入力したって解っているのに、
敢えて後から動的に取得しようとするのですか?
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
With ActiveSheet.Range("A1:A2").Cells .Item(1).Value = "a" .Item(2).Value = "b" Debug.Print .Address(False, False, xlA1, True) End With End Sub
何をどうしたいか、想像が付きません。。。。
(まっつわん) 2020/02/19(水) 22:55
再現します。不思議です。
別プロシージャで処理させようと、Application.Ontimeを仕込みましたが、 そのメソッドもワークしなかったです。
そうなると、何かユーザー定義に似たところもありますね。 ※ただ、ユーザー定義では、これも出来ないので、全く同じとも言えないですけど。 ↓ .Range("A1").Value = "a"
何か代替案を考えるにしても この事情が理解しにくいので考えが進まないです。 ↓ >Workbook.Saveは別のブック(orアドイン)から呼ばれているらしく、 >Workbook.Saveを使用しないというのは難しそうです
> この制限を解消する(もしくは手作業での保存と判別する)方法はありますか。 CurrentRegion.Address が $A$1 なんてことは通常あり得ないから、 その事実を以て簡易判定できるんじゃないですか?
(半平太) 2020/02/20(木) 09:11
(kazuo)さん
やはりBeforeSave内で正しい値が取得できるかあらかじめ確認するしかなさそうですね...。
ありがとうございます。
(まっつわん)さん
すみません、言葉足らずでした。上記のコードはCurrentRegionが正しくないことを再現するためのコードですので、意味はありません。
(半平太) さん
>この事情が理解しにくいので考えが進まないです。
> ↓
>>Workbook.Saveは別のブック(orアドイン)から呼ばれているらしく、
こちらで作成したマクロ付きブックを配布し、各々の端末で利用してもらう想定です。
ですので、その人がどのようなアドインを入れているか、またどのようなブックを同時に開いているかは把握できない状況です。
(このブック以外は開くなとはなかなか言えません...)
例として、以下のようなマクロを含むブックを同時に開いていた場合は不具合が発生してしまいます。
このような状況でも正しく動作するor手作業での保存をさせる必要があります。
'~同時に開いている別ブック.xlsm~
'--さすがにこんなマクロはないと思いますが-- Public sub 開いているブックを全部保存しちゃうぜマクロ() dim wb as workbook for each wb In Workbooks wb.Save next end sub
とりあえずは、BeforeSave内でCurrentRegionなどを呼び出して正しい値が返ってくるかで判定をしようと思います。また、こちらでもなにかわかりましたら追記いたします。
重ねてお礼申し上げます。
(てゃ) 2020/02/20(木) 12:44
BeforeSaveはダメだったですけど、 AfterSaveならCurrentRegionが取得できました。
なので、ワンテンポ遅ればせながら、 そのイベントを回復処理に利用する訳には行かないですか?
※CurrentRegionを使って何をしようとしているのか分からないので 具体案まで行かないですけども。
(半平太) 2020/02/20(木) 19:13
ならば、どのような場面で不具合がありましたか?
代替案も示しましたが、そちらでは不都合ですか?
単にブックを保存するのに、セル範囲に対する操作が関係する場面が思いつけません。
多分UsedRangeの方が使い勝手が良いような気がしますが。。。。
まさか、CSV形式で強制的に保存するためにシート上の数式を消そうとかしている????
(まっつわん) 2020/02/20(木) 22:23
Workbook.Close '別ブックから呼び出し ↓ Workbook_BeforeSave ↓ Workbook_AfterSave '同様の不具合発生
閉じる際に保存させなければよいのですがあまりよろしくないですね...。
(まっつわん)さん
CurrentRegionをどうしても利用しなければならないわけではなく、CurrentRegionのみが使用できないならば別の方法で実装します。
ただし、kazuoさんのコードにもあるようにこの状態ではWorkshhetのプロパティ操作もできなくなっており、どのような操作で不具合が発生するのかわからない状態です。ですので、
>1. Workbook.SaveからWorkbook_BeforeSaveを呼び出した際にはどのような制限がかかっていますか。 >2. この制限を解消する(もしくは手作業での保存と判別する)方法はありますか。 >3. Save以外にClose時にも発生していますが、ほかにどのような状況で発生しますか。
このような質問にいたしました。ご確認ください。
(てゃ) 2020/02/21(金) 12:31
他のマクロからイベントが発生した場合、
一部のメソッド等が無視される仕様みたいです。
Ontimeメソッドとか、
オートフィルターとかも?
WorkBookのイベントで多いのかな?制限?
しかしながら、何が出来て何が出来ないかの文書は公開されてないのかな?
時々、英文の文書を探し出して提示してくれる強者がいたりするので、
そういう人が出てくるのを期待しましょう^^;
(まっつわん) 2020/02/21(金) 16:13
> Workbook_BeforeSave > ↓ > Workbook_AfterSave '同様の不具合発生
なるほどです。
AfterClose なんてイベントは無いですからねぇ。。 お手上げです。
私も一つ、手作業との判別方法を考えました。
※ Application.OnTimeが無視されるのを逆手にとって
Dim calledByCode As Boolean
On Error Resume Next Application.OnTime Now(), "TEST", , False calledByCode = Err.Number = 0 On Error GoTo 0
(半平太) 2020/02/21(金) 19:27
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Cancel = True End Sub
Sub SaveTest() With ActiveSheet .Range("A1").Value = "a" .Range("A2").Value = "b" Debug.Print .Range("A1").CurrentRegion.Address End With '---- ThisWorkbook.Save End Sub
(チオチモリン) 2020/02/21(金) 21:53
検索結果。 マイクロソフトも該当ページに書き写してくれればいいのに。
一部省略してるので、気になる人はアドレスからどうぞ。 898511はGoogleの翻訳を通してるので、原文が気になる人も。
****************************************************************************************************************************************************** https://poweraddress.jp/help/term/menu-command/
メニューから実行する命令、操作、処理 メニューコマンド(menu command)とは、メニューバーやコンテキストメニューから実行する命令のことです。 モードの違いやフィールド選択状態などにより、使用できる項目が変わります。
メニューバーには、[ファイル] や [編集] など、実行可能な命令のメニューが表示されています。 例えば、メニューバーの [編集] には、[コピー] や [貼り付け](Mac では [ペースト])などのメニューコマンドがあります。 ****************************************************************************************************************************************************** https://oshiete.goo.ne.jp/qa/3611324.html
エクセルでWorkbook_BeforeSaveイベントについての疑問
質問者:merlionXX質問日時:2007/12/19 16:04回答数:3件 エクセル2000です。 http://odn.okwave.jp/qa3608360.html の関連質問ですが、これだけでも結構ですのでなにとぞご教示ください。
標準モジュールに以下の3つのマクロを書きました。
Sub text_表示() MsgBox "表示させました。" End Sub
Sub text_非表示() MsgBox "非表示にしました。" End Sub
Sub 保存() ActiveWorkbook.Save End Sub
ThisWorkBookモジュールにこう書きました。
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Call text_表示 Application.OnTime Now, "text_非表示" End Sub
これで、手動でBOOKを保存すると、まず、MsgBox "表示させました。" そして MsgBox "非表示にしました。" が実行され、当然ながら書いたとおりの働きをします。 ところが、Sub 保存() でマクロからBOOKを保存すると、MsgBox "表示させました。" だけが実行され、MsgBox "非表示にしました。"は実行されません。 どうして、Application.OnTime Now, "text_非表示"は無視されたのでしょうか?
------------------------------------------------------------------------------------------------------------------------------------------------------
No.2
回答者: KenKen_SP 回答日時:2007/12/20 00:23 仕様でしょう。
プログラムでブックを保存する場合、BeforeSave イベント内に記載された メニューコマンドは無視されるようです。
恐らく、別スレッドで保存コマンドが実行(非同期)されるようですから 保存中にブックに変更があっては困るからではないかと。(推測・未確認) それで、そのような可能性のあるコマンドは無効化されるのでしょうね。
# Msgbox は大丈夫なんですね。まあ、ブックに変更を与える可能性は # ありませんが、、中途半端だ。
機械翻訳 http://support.microsoft.com/kb/898511/ja?spid=1743&sid=434 原版 http://support.microsoft.com/kb/898511/en-us
余談: 上記 URL の回避策を引用 この問題を回避するために、手動でブックを保存します。
( ゜д゜)ポカーン ****************************************************************************************************************************************************** https://web.archive.org/web/20140310215514/http://support.microsoft.com/kb/898511
プログラムでExcelでブックを保存すると、BeforeSaveイベントでメニューコマンドが実行されません。
記事ID:898511-この記事が適用される製品を表示します。
症状 プログラムでブックをMicrosoft Excelで保存します。 BeforeSaveイベントなどのイベントでメニューコマンドを実行しようとすると、メニューコマンドは実行されません。
原因 この問題は、プログラムで[保存]コマンドなどのメニューコマンドを呼び出すときに、メニューコマンドをコードにネストできないために発生します。 BeforeSaveイベントのメニューコマンドは、実行が明確にブロックされます。
回避策 この問題を回避するには、ブックを手動で保存します。ブックを手動で保存するには、実行しているExcelのバージョンに応じて、次のいずれかの手順を使用します。 ・Microsoft Office Excel 2007で、Microsoft Officeボタンをクリックし、[保存]をクリックします。 ・Microsoft Office 2003およびそれ以前のバージョンのExcelでは、[ファイル]メニューの[保存]をクリックします。 この回避策を使用すると、BeforeSaveイベントで次のメニューコマンドのいずれかを実行できます。 ・[書式]メニューの任意のコマンド。 ・[編集]メニューの[クリア]コマンド。 ・[編集]メニューの[削除]コマンド。 ・[編集]メニューの[行の削除]コマンド。 ・[ファイル]メニューの[印刷]コマンド。
MORE INFORMATION マイクロソフトは、明示または黙示の保証なしに、例示のみを目的としてプログラミング例を提供しています。 これには、商品性または特定の目的への適合性の暗黙の保証が含まれますが、これに限定されません。 この記事は、デモされているプログラミング言語と、プロシージャの作成とデバッグに使用されるツールに精通していることを前提としています。 マイクロソフトのサポートエンジニアは、特定の手順の機能の説明を支援できますが、これらの例を変更して追加機能を提供したり、特定の要件を満たす手順を構築したりすることはありません。
この問題を再現するには、実行しているExcelのバージョンに応じて、次の手順を実行します。
Excel 2007 1. Excelで新しいブックを開きます。 2. [Microsoft Office]ボタンをクリックし、[名前を付けて保存]をクリックし、[ファイルの種類]ボックスで[Excelマクロ有効ワークブック(* .xlsm)]をクリックし、[ファイル名]ボックスにファイル名を入力し、[保存]をクリックします。 3. セルA1にテキストを入力し、Enterキーを押します。 4. [開発者]タブをクリックします。 [開発]タブが表示されない場合は、次の手順を実行します。 a. [Microsoft Office]ボタンをクリックし、[Excelオプション]をクリックします。 b. [人気]をクリックします。 c. [リボン]チェックボックスの[開発者の表示]タブをクリックします。 d. [OK]をクリックして、[Excelオプション]ダイアログボックスを閉じます。 5. [コード]グループの[Visual Basic]をクリックして、Visual Basic Editorを起動します。 6. [プロジェクト-VBAProject]ウィンドウで、[ThisWorkbook]をダブルクリックします。 7. 次の手順を実行します: a. [オブジェクト]ボックスで、[Workbook]をクリックします。 b. [プロシージャ]ボックスで、[BeforeSave]をクリックします。 c. BeforeSaveイベントに次のマクロコードを追加します。
Range("a1").ClearContents
d. 手順7cで入力したマクロコードの下に、次のマクロコードを入力します。
Public Sub Test()
ThisWorkbook.Save
End Sub
8. ブックで、Microsoft Officeボタンをクリックし、[保存]をクリックします。 セルA1のテキストはクリアされます。 9. [キャンセル]をクリックして、[名前を付けて保存]ダイアログボックスを閉じます。 10. セルA1にテキストを入力し、Enterキーを押します。 11. [開発]タブで、[コード]グループの[マクロ]をクリックします。 12. ThisWorkbook.Testマクロをクリックして、[実行]をクリックします。
ブックが保存されると、セルA1のテキストはクリアされません。
プロパティ 記事ID:898511-最終レビュー:2007年1月20日-改訂:4.2
APPLIES TO Microsoft Office Excel 2007 Microsoft Office Excel 2003 Microsoft Excel 2002 Standard Edition Microsoft Excel 2000 Standard Edition
(2u) 2020/02/25(火) 19:47
ありがとうございます。非常に助かります。
特定のメニューコマンドは実行できないんですね。
確かにフォントの変更やオートフィルタも利用できませんでした。
(フォントの色変更やコメント追加などは動作しますので何が正しく動作するのかはわかりませんが。)
Microsoftも別段有用な回避策を提示していませんのでこちらとしても諦めがつきます。
ご回答いただいた方々、本当にありがとうございます。
また何かありましたらよろしくお願いいたします。
(てゃ) 2020/02/26(水) 12:39
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.