Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


4403 / 13646 ツリー ←次へ | 前へ→

【56751】取り消し線の引かれている文字だけ削除 勉強中 08/7/3(木) 14:54 質問[未読]
【56752】Re:取り消し線の引かれている文字だけ削除 ハチ 08/7/3(木) 15:06 回答[未読]
【56756】Re:取り消し線の引かれている文字だけ削除 勉強中 08/7/3(木) 16:37 質問[未読]
【56763】Re:取り消し線の引かれている文字だけ削除 ハチ 08/7/3(木) 17:58 回答[未読]
【56855】Re:取り消し線の引かれている文字だけ削除 勉強中 08/7/8(火) 16:30 お礼[未読]
【56865】Re:取り消し線の引かれている文字だけ削除 ハチ 08/7/9(水) 9:19 回答[未読]
【56916】Re:取り消し線の引かれている文字だけ削除 勉強中 08/7/10(木) 15:36 お礼[未読]

【56751】取り消し線の引かれている文字だけ削除
質問  勉強中  - 08/7/3(木) 14:54 -

引用なし
パスワード
   はじめまして。

たとえばA5からP50の表の各セルにさまざまなデータが入っていて、中には、セル内の一部の文字に取り消し線が引かれているものがあります。

例)「ああああいいいいうううう」 の、「いいいい」だけ取り消し線が引かれている

*取り消し線がまったく引かれていないセルやブランクのセルもあります。
この、「取り消し線が引かれている文字」だけ削除したいと思っています。

例)では「いいいい」を削除して「ああああうううう」にしたいです。

そこで、以下のように書いてみました。

Sub 取り消し文字列削除()
Dim c As Range
Dim i As Integer  
 ActiveSheet.Range("A5").CurrentRegion.Select
  With Selection
  For Each c In Selection 
   Do      
        For i = 1 To Len(c.Value)
      If c.Characters(Start:=i, Length:=1). _
      Font.Strikethrough = True Then          
       c.Characters(Start:=i, Length:=1).Delete         
         End If
    Next
   Loop Until c.Value = "" Or c.Font.Strikethrough = False 
  Next
  End With  
 MsgBox ("取消されている文字列の削除完了")
End Sub

総文字数が100文字ぐらいまでのセルだとうまく取り消し線の引かれている文字だけ削除するのですが、文字数が多いセルで止まってしまいます。

どなたかお知恵を拝借できないでしょうか?
よろしくお願いします。

Excelのバージョンは2003です。

【56752】Re:取り消し線の引かれている文字だけ削除
回答  ハチ  - 08/7/3(木) 15:06 -

引用なし
パスワード
   ▼勉強中 さん:

>総文字数が100文字ぐらいまでのセルだとうまく取り消し線の引かれている文字だけ削除
するのですが、文字数が多いセルで止まってしまいます。

どのようなエラーを表示して止まるのか、書くとわかりやすい回答が付き易いです。

勘で書きますが、
削除系の処理は、オシリからループを回すのが基本です。
削除しながらアタマから処理すると最後の部分で、文字が足りなくなりますよね?

  For Each c In Selection.Cells
    'Do
      For i = Len(c.Value) To 1 Step -1
        If c.Characters(Start:=i, Length:=1). _
          Font.Strikethrough = True Then
          c.Characters(Start:=i, Length:=1).Delete
        End If
      Next
    'Loop Until c.Value = "" Or c.Font.Strikethrough = False
  Next

【56756】Re:取り消し線の引かれている文字だけ削除
質問  勉強中  - 08/7/3(木) 16:37 -

引用なし
パスワード
   ▼ハチ さん:ありがとうございます。

>削除系の処理は、オシリからループを回すのが基本です。
>削除しながらアタマから処理すると最後の部分で、文字が足りなくなりますよね?

そうだったんですか。なにぶん本を見ながらやってる初心者なもので、失礼しました。勉強になります。

>>総文字数が100文字ぐらいまでのセルだとうまく取り消し線の引かれている文字だけ削除するのですが、文字数が多いセルで止まってしまいます。

について、言葉足らずですみません。文字数が多いセルで無限ループになってしまうということです。

ハチさんが教えてくれたとおりにやったらスピードがかなり速くなりました。が、文字数の多いセルについて、文字数を調べたところ、
256文字以内のセル
 →OK
257文字以上のセル
 →取り消し線の引かれた文字を削除しないでマクロが正常に終了してしまいました。(マクロの最後にMsgboxで「終了」と出るようにしています。)

257文字以上は無理なんでしょうか?

何度もで恐縮ですが、よろしくお願いいたします。

【56763】Re:取り消し線の引かれている文字だけ削除
回答  ハチ  - 08/7/3(木) 17:58 -

引用なし
パスワード
   ▼勉強中 さん:

>256文字以内のセル
> →OK
>257文字以上のセル
> →取り消し線の引かれた文字を削除しないでマクロが正常に終了してしまいました。(マクロの最後にMsgboxで「終了」と出るようにしています。)
>
>257文字以上は無理なんでしょうか?

これは、1セルの文字数の制限である256文字を、
超えているから発生しているようです。

こういった場合は、セルの中身を編集するのではなくて、
値を置き換えるコードにすると上手くいきます。

考え方を変えて・・・
1.取り消し線が引かれていない文字を変数に集める。
2.最後に変数の値を、セルの値に置き換える。

こんな感じでどうでしょう?

先にセル自体の.Font.Strikethroughを判定し、
該当セルに処理が必要か、分岐させると、全体の処理をもっと早くできると思います。
必要なら考えてみてください。

Sub Test2()
  Dim c As Range
  Dim i As Long
  Dim buf As String
  
  For Each c In Selection.Cells
    buf = ""
    For i = 1 To Len(c.Value)
      If Not c.Characters(Start:=i, Length:=1). _
        Font.Strikethrough = True Then
        buf = buf & c.Characters(Start:=i, Length:=1).Text
      End If
    Next
    c.Value = buf
  Next
  
End Sub

【56855】Re:取り消し線の引かれている文字だけ削除
お礼  勉強中  - 08/7/8(火) 16:30 -

引用なし
パスワード
   ▼ハチ さん:

ありがとうございます!
257文字以上でもうまくできました。
ただし、ちょっと処理に時間がかかるので、ヒントをいただいた、

>先にセル自体の.Font.Strikethroughを判定し、
>該当セルに処理が必要か、分岐させると、全体の処理をもっと早くできると思います。
>必要なら考えてみてください。

について、とりあえずそのセルの.Font.Strikethroughを判定するのを考えてみました(下記)。が、この場合セル内の文字の一部分だけに取り消し線が引かれているときはそのセルは「取り消し線が引かれていません」と判別されてしまいます。
で、やはりCharactersで1文字ずつ判定するべきかと思ったのですが、それなら結局1文字ずつ見るので結局は一緒かと思い直しました。

度々で恐縮ですがもし何かヒントがありましたらよろしくお願いいたします。

If c.Font.Strikethrough = True Then

MsgBox "取り消し線が引かれています"

Else
MsgBox "引かれてません"

End If

【56865】Re:取り消し線の引かれている文字だけ削除
回答  ハチ  - 08/7/9(水) 9:19 -

引用なし
パスワード
   ▼勉強中 さん:
>
>について、とりあえずそのセルの.Font.Strikethroughを判定するのを考えてみました(下記)。が、この場合セル内の文字の一部分だけに取り消し線が引かれているときはそのセルは「取り消し線が引かれていません」と判別されてしまいます。
>で、やはりCharactersで1文字ずつ判定するべきかと思ったのですが、それなら結局1文字ずつ見るので結局は一緒かと思い直しました。

問題へのアプローチの仕方が良くないと思います。

『全て引かれている』
『全て引かれていない』
『混在している』
この3パターンがあると解っているワケですよね?

コードを拝見すると2パターンの分岐になっています。
うまくいかなくて当然です。

3パターンで『何の値を返すのか?』を検証してみてはどうですか?
ヘルプを見れば、答えは書いてありますけどね^^

'イミディエイトの使い方は調べてください
Sub Test_Chk()
  Debug.Print ActiveCell.Font.Strikethrough
End Sub

【別案】
混在の場合に何の値を返すのか解らなくても、
『その他』という書き方で、うまくいくこともあります。

Sub Test_Sel()
  Select Case ActiveCell.Font.Strikethrough
    Case True
      MsgBox "全て消す"
    Case False
      MsgBox "処理の必要なし"
    Case Else
      MsgBox "1文字づつチェック"
  End Select
End Sub

【56916】Re:取り消し線の引かれている文字だけ削除
お礼  勉強中  - 08/7/10(木) 15:36 -

引用なし
パスワード
   ▼ハチ さん:

ありがとうございました!うまくできました。
(びっくりするぐらい速くなりました)
また、教えていただいたイミディエイトからヒントを得て、取り消し線が引かれていた=削除した文字列とその位置を後で確認できるようにもしました。

このような場所で質問するのは初めてだったのですが、親切丁寧に教えていただき、とても感謝しています。

今度は回答する側になれるよう頑張っていきたいと思います。
ありがとうございました。

4403 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free