[[20080906092221]] 『文字列中の数字の桁そろえ』(ヒロ) ページの最後に飛ぶ

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

 

『文字列中の数字の桁そろえ』(ヒロ)
 WindowsXP、Excel2003
 会社の倉庫に2003のCDがあったので、2000からバージョンアップしました^^

 いつもお世話になっております。
 いろいろ見てみましたが、解りにくかったので質問させていただきます。

 やりたい事は
 入力された住所中の数字の桁数を自動変換でそろえて、ソート時にきれいに並べ替えれ るようにしたいのです。
 例:○○県△△市□□町1丁目12番2号
 これを○○県△△市□□町01丁目0012番0002号のようにしたいのです。
 丁目の前は2桁、番or番地or号の前は4桁といった感じ・・・

 イメージとしては・・・

 d住所をエクセル上のデータとします。

 dim w住所 as string

 w住所 = ""
 do while d住所の文字列の最後まで
    if 数列じゃなかったら
       w住所 = w住所 & d住所の文字列の部分
    else
       select case d住所の数列部分の後ろ
         case "丁目"
              w住所 = w住所 & format(d住所の数列部分,"00")
         case "番","番地","号"
              w住所 = w住所 & format(d住所の数列部分,"0000")
       end select
    end if
    文字列のカウント?
 loop

 こんな感じでできたらいいなぁと思っていますが・・・できるのでしょうか?
 ちなみに、住所は入力時に英数カナを全て半角に変換しております。

 これから、外回りに出かけるので、見るのは夕方以降になると思いますが、
 皆様どうかよい知恵をお貸しくださいm(_ _)mペコリ

 >外回りに出かけるので
 えぇなぁ、そうやって遊んどる間にスカッと処理でけるマクロが手ぇに入るんです
 から・・・。妙に腹立たしくなりますワ。^^
        (弥太郎)
 '------------------
    Dim i As Long, tbl
    tbl = Range("a1", Range("a" & Rows.Count).End(xlUp))
    With CreateObject("vbscript.regexp")
        .Pattern = "\W+(\d+)(丁目|-|−)(\d+)(番|番地|−|-)(\d+)(号)*"
        For i = 1 To UBound(tbl, 1)
            If .test(tbl(i, 1)) Then
                tbl(i, 1) = Replace(Replace(Replace(tbl(i, 1), .Replace(tbl(i, 1), "$1" & "$2"), _
                    Format(.Replace(tbl(i, 1), "$1"), "00") & .Replace(tbl(i, 1), "$2")), _
                        .Replace(tbl(i, 1), "$3" & "$4"), Format(.Replace(tbl(i, 1), "$3"), "0000") _
                            & .Replace(tbl(i, 1), "$4")), .Replace(tbl(i, 1), "$5" & "$6"), _
                                Format(.Replace(tbl(i, 1), "$5"), "0000") & .Replace(tbl(i, 1), "$6"))

            End If
        Next i
    End With
    Range("a1").Resize(UBound(tbl, 1)) = tbl

 15:03 差し替え(汗
       (弥太郎)


 ただいま帰りました・・・
 外回りって・・・・遊んでるように思われてるんですね・・・><
 仕事取ってこないと給料ありませんから、結構大変なんですよ;;
 意外と貧困生活です(;;)ウルウル

 なんだかんだ言いながら、スカッとマクロを教えていただいてありがとうございます。^^
 なんだか、知らないコマンドがいっぱいなので、いろいろ調べながらやってみます^^
 どうせなら、しっかり理解して使いたいですしね^^;

 調べてわからないことも出てくると思いますので、そのときは、またよろしくお願いします。^^;

 (ヒロ)

 >会社の倉庫に2003のCDがあったので、2000からバージョンアップしました^^
・・・これってライセンス規約違反にはならないんですか?


 ライセンス規約・・・・・言われて初めて読みました^^;
 1台につき、1パッケージなんですね><;
 ぜーんぜん知りませんでした^^;
 2000に戻しました;;
 お名前がないので、御礼の言いようもありませんが、
 どなたか存じませんが教えてくださってありがとうm(_ _)m

 さて、ほとんど知らない命令ばっかりだったので、いろいろ調べながらやってみました。
 ユーザーフォームを使用して、入力されたテキストボックスの内容を変換しています。

 パターンが必ずしも決まっていないので、数字を全部4桁にして、最後に、丁目と続く分だけ2桁にするようにしてみました。
 ただ、For Each を使ったからか、同じ数値があった場合8桁になったりしてしまったので、
 前後の文字も読み込むようにして重複を避けるようにしてみたのですが・・・
 弥太郎さんの作ってくれたコードが、まだ全部理解できていないので
 理解できた分だけで作ってみたのですが、なんだか不恰好になってしまいました><;
 わからない部分は、今調べながらやっていますが、とりあえず↓のコードはどうでしょうか?
 改善点などご教授いただければうれしいです^^

 Dim w住所 As String, RE, reMatch, reValue

 ユーザーフォームでの入力チェックにて、エラーがなければ
 w住所 = Textbox1.text
 call 住所変換

 Sub 住所変換()
     Set RE = CreateObject("VBScript.RegExp")
     With RE     '--------------------------文字列中の数値を4桁に変換
         .Pattern = "(\D\d+\D)"
         .Global = True
         Set reMatch = .Execute(w住所)
         If reMatch.Count > 0 Then
             For Each reValue In reMatch
                 w住所 = Replace(w住所, reValue, Left(reValue, 1) & Format(Val(Mid(reValue, 2)), "0000") & Right(reValue, 1))
             Next reValue
         End If
     End With
     With RE     '--------------------------文字列最後の数値を4桁に変換
         .Pattern = "(\D\d+$)"
         .Global = True
         Set reMatch = .Execute(w住所)
         If reMatch.Count > 0 Then
             For Each reValue In reMatch
                 w住所 = Replace(w住所, reValue, Left(reValue, 1) & Format(Val(Mid(reValue, 2)), "0000"))
             Next reValue
         End If
     End With
     With RE     '--------------------------文字列中の数値+丁目を2桁に変換
         .Pattern = "(\d+丁目)"
         .Global = True
         Set reMatch = .Execute(w住所)
         If reMatch.Count > 0 Then
             For Each reValue In reMatch
                 w住所 = Replace(w住所, reValue, Format(Val(Mid(reValue, 2)), "00") & Right(reValue, 2))
             Next reValue
         End If
     End With
     Set RE = Nothing
 End Sub

(ヒロ)


 これではだめなことに気がつきました・・・・
 数字と数字の間の文字が、1個のときに検出されないんですね・・・・><;
 もうしばらく考えて見ます・・・
 (ヒロ)

 えらいっ!
 短時間でよくここまで作成でけましたなぁ。感心します。
 ついでに、住所に有りがちな丁目を省略した 5-13-22 なども桁揃えが欲しいなぁ。
 変数の宣言も忘れずに・・。
 それとwithで括るんは一度だけでよろしいかと思われます。       
       (弥太郎)


 うぅ・・・褒めてもらえたのかな?嬉しいですっ^^
 でもまだ、$1とか$2とかの意味がさっぱりわからない状態です^^;
 ぁ、まだ教えないでくださいね、調べてますので^^

 >それとwithで括るんは一度だけでよろしいかと思われます。
 こういうことですか?
 .Global = Trueもいらないんですかね?・・・・^^;
 まだ、理解が浅いので><;

     Set RE = CreateObject("VBScript.RegExp")
     With RE
 '--------------------------文字列中の数値を4桁に変換
         .Pattern = "(\D\d+\D)"
         .Global = True
         Set reMatch = .Execute(w住所)
         If reMatch.Count > 0 Then
             For Each reValue In reMatch
                 w住所 = Replace(w住所, reValue, Left(reValue, 1) & Format(Val(Mid(reValue, 2)), "0000") & Right(reValue, 1))
             Next reValue
         End If
 '--------------------------文字列最後の数値を4桁に変換
         .Pattern = "(\D\d+$)"
         .Global = True
         Set reMatch = .Execute(w住所)
         If reMatch.Count > 0 Then
             For Each reValue In reMatch
                 w住所 = Replace(w住所, reValue, Left(reValue, 1) & Format(Val(Mid(reValue, 2)), "0000"))
             Next reValue
         End If
 '--------------------------文字列中の数値+丁目を4桁に変換
         .Pattern = "(\d+丁目)"
         .Global = True
         Set reMatch = .Execute(w住所)
         If reMatch.Count > 0 Then
             For Each reValue In reMatch
                 w住所 = Replace(w住所, reValue, Format(Val(Mid(reValue, 2)), "00") & Right(reValue, 2))
             Next reValue
         End If
     End With
     Set RE = Nothing

 >ついでに、住所に有りがちな丁目を省略した 5-13-22 なども桁揃えが欲しいなぁ。
 宿題が出ましたね^^;
 これを解決するには、弥太郎さんのコードを完璧に理解する必要がありそうですね^^
 がんばって解読してみます^^
 また、時間かかるかもしれませんが、結果報告は必ずしますので、見かけたらご指導お願いします。m(_ _)m
(ヒロ)

 おはようございます。
 いろいろ試行錯誤した結果、こんな感じでまとめてみました。
 なんとかうまく処理できている気はしますが、どうでしょうか?

 Dim w住所 As String
 Dim RE As Object
 Dim reMatch As Object
 Dim reMatches As Object
 Dim flg_firstMatch As Integer
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 w住所 = Textbox1.Text
 call 住所変換
 Textbox1.Text = w住所
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

 Sub 住所変換()
     flg_firstMatch = 0
     Set RE = CreateObject("VBScript.RegExp")
     With RE
         .Pattern = "(\D\d+)"                    '<−−1文字+数字のパターンを検出するよう設定(重複回避のため)
         .Global = True                          '<−−文字列全体を検出するよう設定
         Set reMatches = .Execute(w住所)         '<−−マッチング対象となる文字列をセット
         If reMatches.Count > 0 Then             '<−−セットした文字列の中に上記パターンがマッチするものが何件あるか判断し
             For Each reMatch In reMatches       '<−−マッチした分だけ繰り返す
                 If flg_firstMatch = 0 Then      '<−−最初にマッチしたものは丁目部分と判断し全て2桁に変換する
                     w住所 = Replace(w住所, reMatch, Left(reMatch, 1) & Format(Val(Mid(reMatch, 2)), "00"))
                     flg_firstMatch = 1
                 Else                            '<−−2件目以降は4桁に変換する
                     w住所 = Replace(w住所, reMatch, Left(reMatch, 1) & Format(Val(Mid(reMatch, 2)), "0000"))
                     '↑同じ数字が存在しても、変換後02-0002-0002、置き換え対象は-2となり、再変換の場合も-0002が-0002に変換されるだけなので重複の心配はないかと思われます。
                 End If
             Next reMatch
         End If
     End With
     Set RE = Nothing
 End Sub

 自分なりにこうなんだろうと解釈してみたのですが、ヘルプとか難しく書かれているので、果たしてこの解釈でよいのか自信ありません><;
 検証&添削をよろしくお願いいたしますm(_ _)m
 (ヒロ)

 パチパチパチ
 マクロのコードには各自の考え方が反映されるもんですけど、着目点が素晴らしいし、それ
 にも増して短期間でこなしてしまうその能力にも敬意を表します。
 「正規表現品評会」に出展したら金賞候補にノミネートされる事請け合いですわ、えぇ。
  いやぁ、まいったまいった(弥太郎)


 ただいま帰りましたぁ^^
 ぬぬ、一応解釈は合ってるということでいいのかな?

 弥太郎さんホントにありがとうございます。
 おかげさまで、なんとか思い通りの処理もでき、新たな命令も覚えることができました。
 が・・・・
 弥太郎さんに作っていただいたコードを、実際に動かしてみて、デバックポイントを設定したりして、
 何とかここまできたのですが、調べてもすっきりと解釈できない点が・・・・

 >       .Pattern = "\W+(\d+)(丁目|-|−)(\d+)(番|番地|−|-)(\d+)(号)*"
 これは、文字列の組み合わせパターンを考えられる分だけ作ってあるんだなって理解できたのですが、
 \Wは全角文字列という解釈でいいのでしょうか?
 説明を読むと"単語に使用される文字以外の文字にマッチします。[^a-zA-Z_0-9]と同じ意味です。"
 と書いてあるのですが、なんだか解りにくくて・・・・

 >           If .test(tbl(i, 1)) Then
 は上記パターンに当てはまるものについて処理を行うって事だと思いますが、
 Replace文中に使われている"$1"とか"$2"なんですが、文字列中に含まれる、数字の1番目2番目という解釈でよいのでしょうか?
 また、$などの使い方などは、どこを見たらよいのでしょうか?

 最後までお手数かけますが、よろしくお願いいたします。m(_ _)m
 (ヒロ)

 見落としていた点が・・・・
 丁目がなくて最初に番地の場合も、2桁に変換されてしまいますね><;

 仕方がないので 5-13-22 などの場合は4桁変換固定にして、
 丁目が付く分のみ2桁変換することにしました。

 Dim w住所 As String
 Dim RE As Object
 Dim reMatch As Object
 Dim reMatches As Object
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 w住所 = Textbox1.Text
 call 住所変換
 Textbox1.Text = w住所
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 Sub 住所変換()
     Set RE = CreateObject("VBScript.RegExp")
     With RE
         .Pattern = "\D\d+"                      '<−−1文字+数字のパターンを検出するよう設定(重複回避のため)
         .Global = True                          '<−−文字列全体を検出するよう設定
         Set reMatches = .Execute(w住所)         '<−−マッチング対象となる文字列をセット
         If reMatches.Count > 0 Then             '<−−セットした文字列の中に上記パターンがマッチするものが何件あるか判断し
             For Each reMatch In reMatches       '<−−マッチした分だけ繰り返し4桁に変換する
                 w住所 = Replace(w住所, reMatch, Left(reMatch, 1) & Format(Val(Mid(reMatch, 2)), "0000"))
                 '↑同じ数字が存在しても、変換後0002-0002、置き換え対象は-2となり、再変換の場合も-0002が-0002に変換されるだけなので重複の心配はない
             Next reMatch
         End If
         .Pattern = "\d+丁目"                    '<−−数字+丁目のパターンを検出するよう設定
         Set reMatches = .Execute(w住所)         '<−−マッチング対象となる文字列をセット
         If reMatches.Count > 0 Then             '<−−セットした文字列の中に上記パターンがマッチするものが何件あるか判断し
             For Each reMatch In reMatches       '<−−マッチした分だけ繰り返し2桁に変換する
                 w住所 = Replace(w住所, reMatch, Format(Val(Mid(reMatch, 2)), "00") & "丁目")
             Next reMatch
         End If
     End With
    Set RE = Nothing
 End Sub

 一度変換したものを、再度変換しなおすという無駄な処理が入ってしまいますが、
 初心者の私にはここまでかなって気がします^^;
 今後この無駄な部分をなくせるようなコードが組めるよう、
 日々精進していきたいと思っております。
 とりあえず、これで一応の決着ということで^^

 弥太郎さんありがとうございました。
 今後ともよろしくお願いいたします。
 (ヒロ)

 あわわわ、もたもた書いとったら衝突〜。^^
 折角書きましたんで、お問い合わせの件だけ。

 \W+は何の気無しに使いましたが、現実には外国の住所も有る訳ですからあんさんの
 使うてはる\D+が正しいと思います。
 また、○○市××町4丁目5番14号ABCマンション303号室 等という住所も無いとは
 申せまへんから
 .Pattern = "\D+(\d+)(丁目|-|−)(\d+)(番|番地|−|-)(\d+)(号)*(.+)*"
 とするのがベターでせう。一発で検索しますからGlobalは不要です。

 $の使い方なんですが
 $1 とか $2とか以外にも
 $&  &` &_ &' &nn &+ 等が有るようです。(現実に使うた事はありません)
 正規表現でググッて見つけたもんですけど、今検索しても見つける事がでけまへんで
 した。じっくり捜してみてくらはい。

 $1とか$2とかの数値は( )で囲まれた文字列の左からのIndexになっとります。
 ステップインして
 a1=.replace(tbl(i,1),"$1")
 a2=.replace(tbl(i,1),"$2")
 a3=....
 a4=....
 を確認されれば良くお分かりになると思われます。

 かっこ内の|で区切ったデータはOrと同じ意味を持ちます。
 ですから$2は丁目Or-Or−という事になります。

 なお、この作業はソートする際に用いるとの事ですが
[[20080910113406]]
 のような方法もあります。
        (弥太郎)


 おはようございます。
 ググッて見つけました
 http://www.ruby-lang.org/ja/man/html/_C1C8A4DFB9FEA4DFCAD1BFF4.html#a.242
 が、読んでもよくわかりません^^;ある程度知識のある人向けなんですかね・・・・
 弥太郎さんの説明の方が親切でわかりやすいですね^^

 教えていただいたコードを、私がやろうとしていることに当てはめるなら、
 こういうことになるのでしょうか?
 $7$8の部分は、適当にこうしてみようとしただけなんで気にしないでください^^;
 やっと、すっきり理解できたような気がします^^

 Dim w住所 As String
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 w住所 = Textbox1.Text
 call 住所変換
 Textbox1.Text = w住所
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 Sub 住所変換2()
     With CreateObject("vbscript.regexp")
         .Pattern = "\D+(\d+)(丁目|-|−)(\d+)(番|番地|−|-)(\d+)(号)*(\D+|\d+)(\d+|\D+)*"
         If .test(w住所) Then
             w住所 = Replace(Replace(Replace(Replace(w住所, .Replace(w住所, "$1" & "$2"), _
                 Format(.Replace(w住所, "$1"), "00") & .Replace(w住所, "$2")), _
                     .Replace(w住所, "$3" & "$4"), Format(.Replace(w住所, "$3"), "0000") _
                         & .Replace(w住所, "$4")), .Replace(w住所, "$5" & "$6"), _
                             Format(.Replace(w住所, "$5"), "0000") & .Replace(w住所, "$6")), _
                               .Replace(w住所, "$7" & "$8"), Format(.Replace(w住所, "$7"), "0000") & Format(.Replace(w住所, "$8"), "0000"))  
         End If
     End With
 End Sub

 弥太郎さん、ホントに最後までご親切にありがとうございました。
 モヤモヤもすっきりして解決です^^

 リンク先の『住所の並べ替え』を使ったほうが、見た目にはよさそうなので、
 そちらも合わせて勉強させていただきます。
 原理としては、正規表現を使って裏でソートするという感じですね 
 まだ、チラッと見ただけですが^^;
 今回勉強した事が役立ちそうです^^
 (ヒロ)

コメント返信:

[ 一覧(最新更新順) ]


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