• ベストアンサー

エクセルVBAでセルのFormulaHiddenが失敗!?

エクセル2000です。ブック内の全シートの計算式を非表示にするため以下のマクロを作成しました。 ところが実行時エラー1004「RangeクラスのLokedプロパティを設定できません」とエラーになります。 どうも結合セルがひっかかるようですが、理由がわかりません。 ご教示願えませんでしょうか? Sub Formula_Hidden() For Each ws In Worksheets ws.Activate For Each C In ActiveSheet.UsedRange If C.HasFormula = True Then C.Locked = True C.FormulaHidden = True i = i + 1 End If Next C Next ws MsgBox i & "個のセルをFormulaHiddenしましたよん。" End Sub

質問者が選んだベストアンサー

  • ベストアンサー
  • taocat
  • ベストアンサー率61% (191/310)
回答No.9

こんにちは。 暫く振りに訪ねてみれば、またまたヘンテコなことにトライしておりまするねぇ。。(^^; ヘンテコに興味あり、ということで一案。(^o^) ----------------------------------------------- Sub MerlionXX()  Dim Sht As Worksheet  Dim Cnt As Long  On Error Resume Next  For Each Sht In Worksheets    With Sht.Cells.SpecialCells(xlCellTypeFormulas)      .Locked = True      .FormulaHidden = True      Cnt = Cnt + .Cells.Count    End With  Next Sht    MsgBox Cnt & " 個のセル云々" End Sub ----------------------------------------------- それから、 >でも変ですねえ、WendyさんのもActivateしてないのに同じSpecialCellsで認識してるのに・・・。 これ、Merlionさんの勘違いではありませぬか? で、お訊きします。 「動作しない」とはどんな”状態”のことを仰っているのでせう。 少々興味ありです。 ところで、Merlionさん、 当方の尊敬する回答者のお二人、Wendy02さん、KenKen_SPさんのコードに ちょっとした、場合によっては重大な、ケアレスミスがあることにお気づきでせうか? コードを眺めただけでそれがお分かりになりましたら 次からは「お師匠さま」とお呼びせねばなりますまいねぇ。。(^o^)~~ 以上です。

merlionXX
質問者

お礼

道士さま、こんばんは。 ヘンテコですか?けっこう使うと思うんですが・・・・。 だから個人用マクロに書いてしまい、作動しなかったようです。 ご教示のコードは完璧に作動しました。ありがとうございます。 > 場合によっては重大な、ケアレスミスがあることにお気づきでせうか? 何度か試して気づいたのですが、一旦Setしたシートごとの対象範囲が、クリアされていない、またはクリアする位置が違っているため、数式が存在しないシートがあった場合、個数を正しくカウントしないということでしょうか?

その他の回答 (11)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.12

taocat 様、Wendy02です。 どうも、ご指摘ありがとうございます。 >式の無いシートでは、その前のシートのセル範囲(シートも含む)が >そのまま引き継がれてしまう、ということです。 今、試してみました。 Sheet1, Sheet2, Sheet3 で、Sheet2 は、まったくの空の状態にし、SpecialCellsで、エラーが発生するように作り、Sheet3 は、2箇所の結合セルと一般の数式セルを置きました。ws に、Sheet2 が入ったときに、ステップモードで見てみると、前のSheet1のシートを繰り返していました。SpecialCells の内容は、Sheet 情報から入っているようですから、クリアしなければ、同じものを、再び、チェックしています。 私の試した方法では、問題はでなかったのですが、ループを繰り返していますから、無駄ですね。 (まあ、私のすることですから、何が抜け落ちでもあるかもしれませんが、ダメならダメでしょうがないとします。) ループの最後の手前で、  Set rng = Nothing 'ここを加筆  Next ws とすればよいのかな? なお、カウンターは以下のようにしてみました。 'カウンター     If .FormulaHidden = False Then      If .MergeCells Then       i = i + 1      Else        i = i + .Cells.Count      End If     End If      私は、この件は、深追いするつもりはありませんが、もし、よかったら見てやってください。

merlionXX
質問者

お礼

ありがとうございました。 今回も大変お世話になりました。

  • taocat
  • ベストアンサー率61% (191/310)
回答No.11

こんばんは、お師匠さま ← お約束、(^o^)~~ >Setしたシートごとの対象範囲が、クリアされていない >数式が存在しないシートがあった場合、個数を正しくカウントしない Good Job! その通りです。 式の無いシートでは、その前のシートのセル範囲(シートも含む)が そのまま引き継がれてしまう、ということです。 On Errorを利用するときはそこら辺りのことには十分注意払いませう。 それからコードを眺めてみればお分かりになると思いますが、 Wendy02さんのではそれは表には現れませんが同じことです。   >ヘンテコですか?けっこう使うと思うんですが・・ いつもいつも、「色んなことにトライされてますねぇ」ではちょと芸がないなと思い。。。(^^;     KenKen_SPさん、こんばんは。 今回は重箱の隅的な発言、失礼しました。 それもこれも好奇心旺盛な、merlionXXさんの為、 ということでお許しください。 何れにしろ、KenKen_SPさんのコードは非常に参考になりますので 目につけば必ず読むようにしています。 これからも宜しくお願いいたします。  

merlionXX
質問者

お礼

ありがとうございました。 今回も大変お世話になりました。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.10

> 個人用マクロブックのPERSONAL.xlsにコピペしていたのです。 ああ、、それなら ThisWorkbook ではなく、ActiveWorkbook ですね。了解 です。それから、Sheets コレクションは使う意味がないので、Worksheets コレクションに訂正します。 Dim Sh As Worksheet と宣言もしていますのでm(__)m > ちょっとした、場合によっては重大な、ケアレスミスがあることにお気づき > でせうか? わかりました。ご指摘ありがとうございました。こちらの修正は、merlionXX さんにお任せします。 間違い等は、お気遣いなくご指摘いただけると非常に助かります。ありがとう ございました。

merlionXX
質問者

お礼

ありがとうございました。 今回も大変お世話になりました。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.8

> でも変ですねえ、WendyさんのもActivateしてないのに同じSpecialCellsで認識してるのに・・・。 気なしに、#4 では Sheets コレクションを使っているのですが、これが原因 かもしれません。Worksheets コレクションなら大丈夫かも... これも確証はないのですが。   For Each Sh In ThisWorkbook.Sheets      ↓   For Each Sh In ThisWorkbook.Worksheets 興味本位で申し訳ないのですが、このように変更した場合でも Sh.Activate が必要でしょうか? よろしければですが、結果を教えてもらえるとうれしいです。

merlionXX
質問者

お礼

原因がわかりました! わたしのミスです。 実は、このコードを個人用マクロブックのPERSONAL.xlsにコピペしていたのです。 だから、For Each Sh In ThisWorkbook.Sheetsでも For Each Sh In ThisWorkbook.Worksheetsでもダメだったんですね? Activateを入れてうまく行ったのは、こっちはエクセルのBOOKに書いてみたからなのだと思います。 For Each Sh In Worksheets としたら、個人用マクロでもActiveにしなくとも大丈夫でした。 お騒がせいたしました、すみません、

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.7

> やってみましたが、作動しません。 あら? Excel2002 だと動作してますけど(´・ω・`)? > Sh.Cells.SpecialCells(xlCellTypeFormulas, ALL_TYPE)を認識できてない > ようでした。 Excel2000 とかだと、直前にシートを Activate しないと、SpecialCells が 失敗するのかも。試す環境がないので、自信なしです。 Sh.Activate '<--------追加 Set rngHasFormula = _   Sh.Cells.SpecialCells(xlCellTypeFormulas, ALL_TYPE)

merlionXX
質問者

お礼

ありがとうございます。 おっしゃるとおりSh.Activate の追加でOKでした。 でも変ですねえ、WendyさんのもActivateしてないのに同じSpecialCellsで認識してるのに・・・。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

>ただ、セルの数が数えられなくなりましたが。(Areaを数えてるようですね) そうでした。 MsgBox i & "個をFormulaHiddenしましたよん。" セルで数えたら、結合したところを、セルの数だけ数えているのは、なんとなく不自然に感じました。実際の、その場所(Area)をロックして、数式非表示にしたことを数えています。セルは、単なる論理的な数ですね。色づけしてみて、そのほうが、良いように感じました。 まあ、それは、お好きなように!

merlionXX
質問者

お礼

ありがとうございます。 Areaにすると、結合してなくとも、たとえばA1:A10にそれぞれ数式が入っていても、その範囲が1個と数えられてしまいますよね?それではちょっと不都合だったものですから。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

元のコードをそのまま加筆してみました。 要点は、2点  ・SpecialCellsで取った場所はセルではなくて、Area にする  ・カウンターの取り方 '----------------------------------------------------- Sub Formula_Hidden_Wendy()  Dim a As Range  Dim ws As Worksheet  Dim rng As Range  Dim i As Long  For Each ws In Worksheets   On Error Resume Next   Set rng = ws.Cells.SpecialCells(xlCellTypeFormulas, 23)   'Formula Types include All = 23   On Error GoTo 0   If Not rng Is Nothing Then    For Each a In rng.Areas    With a    'カウンター     If .FormulaHidden = False Then       i = i + 1     End If     .Locked = True     .FormulaHidden = True     '.Interior.ColorIndex = 3 '色づけ確認用    End With    Next a   End If  Next ws  MsgBox i & "個のセルをFormulaHiddenしましたよん。" End Sub '-----------------------------------------------------

merlionXX
質問者

お礼

Wendy02さん、お久しぶりで~ス!!。(^o^)/ ありがとうございました。 Area にすると結合しててもOKなんですね。 ただ、セルの数が数えられなくなりましたが。(Areaを数えてるようですね)

merlionXX
質問者

補足

i = i + a.Cells.Count でセルの数も取得できました。ありがとうございました。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.4

こんばんは。 結合セル判定は、 IF RangeObject.MergeCells Then でできます。 が、単独セルで MergeArea プロパティーを使っても単独セルを返すだけなので、 結合セル判定は必要ないかも。 Sub Formula_Hidden()      Dim rngHasFormula As Range   Dim Sh      As Worksheet   Dim i       As Long   Dim C       As Range      Const ALL_TYPE = xlErrors Or xlLogical Or xlNumbers Or xlTextValues   For Each Sh In ThisWorkbook.Sheets     On Error Resume Next     Set rngHasFormula = _       Sh.Cells.SpecialCells(xlCellTypeFormulas, ALL_TYPE)     On Error GoTo 0     If Not rngHasFormula Is Nothing Then       For Each C In rngHasFormula         With C.MergeArea           .Locked = True           .FormulaHidden = True         End With         i = i + 1       Next C     End If   Next Sh   Set rngHasFormula = Nothing   ' 結合セルの数が含まれる   MsgBox CStr(i) & "個のセルをFormulaHiddenしましたよん。" End Sub

merlionXX
質問者

お礼

ありがとうございます。いつもお世話様です。 やってみましたが、作動しません。 On Error Resume Nextを削除したところ、 Sh.Cells.SpecialCells(xlCellTypeFormulas, ALL_TYPE)を認識できてないようでした。

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.3

SpecialCellsで数式のセルを選択したらいけそうでした。コードは整理していません。悪しからずです。 Sub Formula_Hidden() For Each ws In Worksheets  ws.Unprotect  ws.Activate  ws.Cells(1, 1).Select  Selection.SpecialCells(xlCellTypeFormulas, 23).Select  Selection.Locked = True  Selection.FormulaHidden = True  i = i + Selection.Cells.Count  ws.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True Next ws MsgBox i & "個のセルをFormulaHiddenしましたよん。" End Sub

merlionXX
質問者

お礼

な~るほど! こういうやりかたもあるんですね。セルをFor next で探さなくともいいですね。 勉強になりました。 ありがとうございます。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

的外れかもしれないが、下記では改善されませんか。 Sub Formula_Hidden() Dim c As Range Dim ws As Worksheet For Each ws In Worksheets ws.Activate MsgBox ws.Name MsgBox ActiveSheet.UsedRange.Address For Each c In ActiveSheet.UsedRange If c.HasFormula = True Then MsgBox c.Address c.Locked = True c.FormulaHidden = True i = i + 1 End If Next c ActiveSheet.Protect "", True, True, True Next ws MsgBox i & "個のセルをFormulaHiddenしましたよん。" End Sub Msgboxは確認のために入れたもので、意味はありません。

merlionXX
質問者

お礼

ありがとうございます。 やはり結合セルでえらーになってしまいます。

関連するQ&A

  • エクセルVBAでUsedRange内の可視セルを指定する方法

    UsedRange内の可視セル限定で、ロックされていない場合、データをクリアしたいのです。 以下のようなコードを書いてみましたがSpecialCellsのところでコンパイルエラーになってしまいます。 どのように直せばよいのでしょうか? Sub シートクリア() Application.Calculation = xlCalculationManual Application.EnableEvents = False For Each c In Intersect(SpecialCells(xlCellTypeVisible), ActiveSheet.UsedRange) If c.Locked = False Then c.MergeArea.ClearContents End If Next Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True End Sub

  • エクセルVBAでLockされてないセルをClearContents

    エクセル2000です。 シートでロックされていないセルだけ中身を削除するマクロを作っています。以下でも一応作動はするのですが、いちいちForNextでまわさずにできないものかと質問させていただきました。 よろしくお願いします。(o。_。)oペコッ Sub クリアテスト() Dim c As Range For Each c In ActiveSheet.UsedRange If c.Locked = False Then c.ClearContents End If Next End Sub

  • Excel 2000にて特定のシート(シート名 1~30)セル保護をし

    Excel 2000にて特定のシート(シート名 1~30)セル保護をしていないデータ(結合セルを含む)を一括削除を行いたいのですが、サイトで見つけた物を使用してみたのですが、うまくいきませんでした。 よろしくお願いします。 Sub test2() ? Dim c As Range ? With ActiveSheet ??? .Unprotect ??? For Each c In .UsedRange ????? If Not (c.Locked) Then c.MergeArea.ClearContents ??? Next ??? .Protect UserInterfaceOnly:=True ? End With End Sub シートは40枚程あるのですが、削除したいのはシート1~30迄のデータです。 マクロのレベルは初級レベルです。 よろしくお願いします。

  • Excel VBAで結合セルの扱いが失敗します。

    KenKen_SPさんの素晴らしいコードを参考に、特定の色のセルにおいてのみ、テキストを削除するマクロが以下です。このままでは結合セルのあるエクセルシートでエラーになってしまいます。 これを解決できませんでしょうか。よろしくお願いします。 For i = 1 To ThisWorkbook.Worksheets.Count ThisWorkbook.Worksheets(i).Select Dim C As Range For Each C In ActiveSheet.Range("A1:M55") If C.Interior.ColorIndex = 6 Then '6 - YELLOW C.ClearContents End If Next Next

  • VBA どこでもセル選択

    教えて頂いたVBAなのですがもう一つ Sub Macro1() Dim Ws01 As Worksheet Dim Counter As Long, i As Long, j As Long Dim INP As String Set wS = Worksheets("Sheet4") wS.Cells.ClearContents For i = 3 To ActiveSheet.UsedRange.Rows.Count INP = "" For j = Selection(1).Column To Selection(Selection.Count).Column If Cells(i, j) = 1 Then INP = INP & Cells(2, j) & "," End If Next j Counter = Counter + 1 If INP <> "" Then wS.Cells(Counter, "A") = Left(INP, Len(INP) - 1) End If Next i End Sub -------------------------------------------------------------- For i = 3 のところを3としないでどのセル(行)にも対応させたいのですが どうすればいいでしょうか?

  • もしも新規Excelファイルを開いてる場合は閉じる

    Excel2003です・ ユーザーが新規Excelファイル(book1)かテスト用ファイルを開いている場合は閉じる処理を考えております。 Option Explicit Dim ws As Workbook, flag As Boolean Private Sub Workbook_Open() For Each ws In Workbooks If ws.Name = "Book1" Then flag = True Next ws If flag = True Then Workbooks("Book1.xls").Close   Else   End IF For Each ws In Workbooks If ws.Name = "テスト用.xls" Then flag = True Next ws If flag = True Then Workbooks("テスト用.xls").Close   Else   End IF End Sub このコードだとBook1を開いているのに、Trueで拾ってくれません。 ws.Name = "Book1.xls"にしても同じです。 どこかおかしい部分があるのでしょうか?

  • 【help】Excelデータが消えました。

    this work bookで下記のコードを入れ、間違えて閉じてしまった後からそのページにあったファイルが消えてしまいました。 復旧は可能でしょうか? ちなみに現在の状況はbook2から始まる状態で、消えたはずのbook1の合計の関数を示しています。どなたかわかる方教えてください!! Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) For Each ws In Sheets If ws.Name = "Dummy" Then ws.Visible = True Else ws.Visible = xlSheetVeryHidden End If Next End Sub Private Sub Workbook_Open() Dim ws As Worksheet For Each ws In Sheets If ws.Name = "Dummy" Then ws.Visible = xlSheetVeryHidden Else ws.Visible = True End If Next End Sub (seiya)

  • [VBA] For文の使い分けについての疑問

    こちらの識者の方々にはいつもお世話になっています。 VBAの質問です。 環境は下記になります。 OS=windows7 pro 64bit Office=Excel2010(14.0.7128.5000) ・疑問点 For each nextもFor nextも、最下行まで処理をしたいときに使用することが多いのですが、 単列の場合はFor each next、複数列の場合はFor nextというような使い方をしています。 例:For each next Sub test()  Dim ws As Worksheet  Dim r As Range  Dim endRow As Long  Set ws = ThisWorkbook.Sheets(1)  endRow = ws.Cells(Rows.Count, 1).End(xlUp).Row  For Each r In ws.Range("A1:A" & endRow)   If r.Value Mod 2 = 0 Then r.Font.Bold = True  Next r End Sub 例:For next Sub test2()  Dim ws As Worksheet  Dim i As Long  Dim endRow As Long  Set ws = ThisWorkbook.Sheets(1)  endRow = ws.Cells(Rows.Count, 1).End(xlUp).Row  For i = 1 To endRow   If ws.Cells(i, 1).Value Mod 2 = 0 Then ws.Cells(i, 1).Font.Bold = True   If ws.Cells(i, 2).Value Mod 3 = 0 Then ws.Cells(i, 2).Font.Bold = True  Next i End Sub 単純に、複数列での処理をする場合にはFor each next文を2つ書かないといけないと思い(込み)、 上記のような運用にしていますが、そもそもこの考え方は合っていますでしょうか? 単列の処理であってももちろんFor next文で問題なく使用できますし、 複数列の処理の場合もFor each next文で処理することはできます(冗長ですが)が、 VBA的に正しいというか、合理的な考えであるのかどうかが疑問です。 みなさんはFor each nextとFor nextをどのように使い分けていますか? 質問に不備不足等ございましたらご指摘ください。 ご面倒お掛けしますがよろしくお願いします。

  • エクセルVBAで DirectPrecedentsプロパティ

    DirectPrecedentsプロパティが同一シート内しかトレースできないことを利用して、他シートを参照しているセルを判定できないかと思い、下記のマクロを書いてみました。 残念ながら他シートを参照しているセルでエラーになってしまいます。 どのよに修正すればよいでしょうか? なお、他シート参照の判定に"!"の存在を使わないのは、「名前定義」されたセルを参照している場合を想定しているためです。 Sub TEST01() With ActiveSheet On Error GoTo line For Each c In .UsedRange.SpecialCells(xlCellTypeFormulas, 23) On Error GoTo 0 c.Select If c.DirectPrecedents.Address = "" Then'ここでエラー MsgBox c.Address & "は他シート参照" Else MsgBox c.Address & "は" & c.DirectPrecedents.Address & "参照" End If Next End With line: MsgBox "数式がありません。" End Sub

  • エクセルVBAで保護したシート内の書式設定を可能にしたい

    お世話になります。 『記入可能セルに記入させ、「送信」フォームを押すと、1箇所文字の色が変わり、添付されてメールで送られる。』というマクロを組みました。 その後、 シートがたくさんあるので、VBAを使って、一度にシートの保護、非保護を行いました。 以下はその記述文です。 Sub 保護() Dim Ws As Worksheet For Each Ws In Worksheets Ws.Protect Password:=111 Next End Sub Sub 保護解除() Dim Ws As Worksheet For Each Ws In Worksheets Ws.Unprotect Password:=111 Next End Sub この保護のマクロを使うと、記入可能なセルは、セルの書式設定の保護タブからチェックをはずしており全く問題ないのですが、 「色が変わる」という設定がエラーになります。 どのようにしたら、色が変わるのも許可されるマクロになるのでしょうか。 ご教示お願いいたします。

専門家に質問してみよう