<HOME  <お願い事項   <Access2002 TOP   <Access97 TOP   <サイト内検索
 MS-Access2000--VBAの小屋>数字を漢字にする関数
   1  2  3  4  5  6  7  8



処理の流れとしては、

 1)どっかしらか、漢数字に変えたい値を取ってくる。扱いはテキスト型。
 2)一番右端の(一の位)の数字を判断し、漢数字に変える。
 3)右から2番目の(十の位)の数字を判断し、漢数字に変え、"十"という字を右側に添える。ただし数字が1の場合は、一はいらない。
 4)右から3番目の(百の位)の数字を判断し、漢数字に変え、"百"という字を右側に添える。ただし数字が1の場合は、一はいらない。
 5)右から4番目の(千の位)の数字を判断し、漢数字に変え、"千"という字を右側に添える。
 6)右から5番目の(万の位)の数字を判断し、漢数字に変え、"万"という字を右側に添える。

という感じですね。
・・・これって、必ず5桁の数字が対象になるわけじゃないですよね。3桁の場合もあるし、2桁のときもある。
つまり、場合によっては3)から下は、やらなくてもいいかもしれないってわけですね。
それって、どういうときですか?














どうです?









つまり・・・。
1)でゲットした値が、たとえば3桁である場合は、4)までやればよくて、5)と6)は必要ないですよね。
そう。最初に、「何文字(何桁)か」を調べて、その数だけ処理を繰り返すっていう考え方で、なんとかいけるんじゃないかと思います。

 1)どっかしらか、漢数字に変えたい値を取ってくる。扱いはテキスト型。
 2)その値の文字数を調べる。この数字をとりあえず2)と呼ぶ。3桁だったら"3"という数値になる。
 3)以下の処理を、2)回くりかえす。
    右端から2)文字目の数字を、該当する漢数字に変える。
    2)が2だったら十、3だったら百、4だったら千、5だったら万という字を、左側に添える。

3)の部分の処理は、もうちょっとすっきりできると思いますが、まずはここまで、状況を整頓してみてください。


さて、んじゃここまでの内容、作ってみましょうか。
モジュールを新規作成し、その中になんか適当な名前のプロシージャを作ります。

前回「稼働日テーブル」とか「昨日の二倍の宝石を」とか「年齢計算」のとき、あんまりお話しなかったですが、みなさんだいたい「どういうのがSubで、どういうのがFunctionか」って、オッケーでしょうか??実際、これがわかんないとVBAお話にならないとは思うんですが・・・でも、こういうのって・・・プログラミングの雰囲気になれてなかったりキャリアが浅かったりすると、こういうのこそわかりにくいんじゃないかって、わたしは思うんですね。

「稼働日テーブル」は、ある条件をもとにテーブルを作成しました。Subプロシージャです。
「年齢計算」は最初Subプロシージャでしたが、クエリとかフォームのコントロールソース欄で動かして使いたかったのでFunctionプロシージャに変えました。
Subプロシージャとは、「ずらずらずらーっといろんな処理をして終わる」タイプのプロシージャです。
Functionプロシージャとは「ずらずらずらーっといろんな処理をして何かしら答えを出す」タイプのプロシージャです。

といっても、なかなかわかりにくいんですが・・・。

 hebohebo

というプロシージャがあったとして、これがSubの場合は1行ずつ処理をやって終わります。イメージとしてはマクロの実行と同じようなものです。Fnctionだと、中で計算された答えが返ってきます。Date関数とかInt関数とかFormat関数とかと同じですね。
「稼働日テーブル」の場合は、テーブル作って終わりました。だからSubプロシージャ。年齢計算は、誕生日をもとに「年齢」を返してもらいたいので、Functionプロシージャです。

今回は、「与えた数字を漢数字にして返してもらいたい」ので、そんなわけでFunctionプロシージャとして作り始めます。
こういうのは、ほんとに、いろいろ作ってみて実感していってくださいね。
Functionプロシージャじゃないとできない処理をSubプロシージャとして書いても動かないですから、いろいろ繰り返しやっていくうちにきっと見えてくると思います。


処理の骨組みはこんな感じかなぁと思うんですが、どうでしょう?

あとはFor Nextの間の処理を考えればいいんですよね。(それが一番の問題なんだが)
ええと、まずは、「一番右端から何文字目」っていうのを考えないといけないですよね。これは、Mid関数というやつをうまいこと使ってみましょう。

詳しくはヘルプ見てください。
Mid(なにを,何文字目から,何文字分)取り出すか、っていう関数です。使えるのはテキスト型のフィールドだけ。数値型のフィールドにこの関数使ってもダメです。っていうのは、みなさんもうオッケーですよね。
ではちょっとばかり実験です。For Nextの2行をちょっとばかりコメントアウトして(一番左側にシングルコーテーションをつけて、処理から除外する)テストします。

S1には、ちょっと長めの数字を入れておきます。わたしは41569って代入しました。あ、これ、なんでダブルコーテーションで囲ってるか・・・わかんない、っていう人は・・いらっしゃらないですよね???テキスト型の変数に代入するから、ですよ。文字として扱ってもらうからです。
で、Function名に直接、Mid関数で取ってきた値を代入するようにして、イミディエイトウィンドウで試してみましょう。
41569の左から(文字列扱いなので)5桁めの文字を1文字だけ、取ってきますか?
答えがちゃんと返ってくればオッケー。これ、使えそうですね。

ループ1回目:一番右端(一の位) → Mid(S1, L1, 1)
ループ2回目:右から2番目(十の位) → Mid(S1, L1- 1, 1)
ループ3回目:右から3番目(百の位) → Mid(S1, L1- 2, 1)
ループ4回目:右から4番目(千の位) → Mid(S1, L1- 3, 1)
ループ5回目:右から5番目(万の位) → Mid(S1, L1- 5, 1)

こんな感じでいけそうじゃないですか?
そうなると・・・

 ループα回目:右からα番目(○の位) → Mid(S1, L1 ? α + 1, 1)

まず、これで、取り出す文字を指定することができそうですね。αは、For Nextの中で使ってる i という変数を使ってみましょう。

で、実際の処理は、というと・・・。

 A)上記処理で取り出した数字を、漢字にする。
 B)何文字目かによって、十、百、千、万をつける。

のふたつの処理をするわけです。これは、If文もしくはSelectCase文でなんとかしましょう。難しいとこは、上記のふたつの処理は入れ子じゃなくて並列なので、両方ともチェックしなくちゃならないとこです。A)とB)って、「八だったら百ってことはありえない」とか、そういう関係じゃないですもんね。

そうなると・・・。

For .....
   1)もしも、Mid(S1, L1 ? α + 1, 1) が 1だっがら一、2だったら二、3だったら三・・・・・
   2)もしも、α がL1だったら何もしなくていいけど、αがL1-1だったら2桁目ってことだから十、αがL1-2だったら3桁目ってことだから百・・・。
3) = 1) & 2) & 3)
Next

っていうループになりそうです。

3) = 1) & 2) & 3)  ← これがミソなんですけど、これっていわゆるループですから、For Nextを繰り返すわけで、その都度、一の位、十の位、百の位・・・・・の、1)と2)を算出するわけです。
毎回どこかに値を残していかないと、一番最後の位の漢字しか残んなくなっちゃいますよね。
そして、最終的な答えは漢字交じりですからテキスト型なので、+じゃなくて&で結び付けます。

そうすると・・・ずいぶんたくさん条件判断をしなくちゃならなそうなんで・・・1)2)3)を、それぞれ専用の変数設けて作るようにしましょうかね。

で、最後の最後で、3)をFunction名に代入すればオッケーのはずです。