bar_1

contents_map

2010年8月23日月曜日

ExcelVBA漢数字を数値に変換するマクロ


Sep. 2nd, 2011追記:久々に見なおしてみたら、千、百、十などの小さなくらいの処理にバグを見つけた。修正したものを github に格納している。下記のコードも更新した。



またこの修正に伴い、新たに、壱萬などの漢字表記による漢数字もサポートする仕様追加を行った。



官公庁の発表している文書を読んでいるときに、グラフにしてみたいデータが有っ
た。そのデータ部分をコピペで、Excelに張り付けていた。


ところが、そのデータは漢数字で表記されていたのだ。当然このデータは、セル
上で文字列(String)として認識される。グラフを作成するのためには、数値デー
タが必要だ──漢数字を、いちいち手打ちで数値に修正するのはバカバカしい…
下向いちゃうし。

 

このような思いから、Excelで、漢数字を数値に変換する方法についてぐぐってみたところ、似たようなニーズがあったようで、いくつか参考となるVBAマクロを見つけることができた。


しかし、この例の場合は

  • 4桁までの数字+位を表す漢数字という形式

  • 位が固定

  • データの指定方法がセルのみ

などの点で、一般性にかけるように思われた。



そこで、当方で

  • 二千十、二〇一〇、2千十、いずれの表記も可

  • 〇~京の単位まで、柔軟に使用可

  • 引数は、セル、もしくは文字列いずれも使用可


であるような、マクロ関数(Function): STRINGNUMBER を作ってみた。




Attribute VB_Name = "KanNum"
'''' KanNum.bas
'
'
'Author: mephistobooks (http://voidptr.seesaa.net)
'Date: 2010 Aug. 13
'Updated: Sep. 1st, 2011 bugfix (千, 百, 十)
'
''' as use stricts in Perl;
Option Explicit
'Private Const DEBUG_KANNUM = True
Private Const DEBUG_KANNUM = False
'NAME
'  STRINGNUMBER
'
'SYNOPSIS
'  =STRINGNUMBER(v)
'  v は、漢数字で書かれた、セルまたは文字列
'
'
'DESCRIPTION
'  漢数字を数値に変換する。数値を漢数字に変換する関数:NUMBERSTRING の逆を行う。
'  漢数字は、京の単位まで指定できる。
'  漢数字の指定方法は、セルまたは文字列で指定できる。
'  漢数字の表記は、下記の例のいずれにも対応:
'
'  例.
'       STRINGNUMBER("一九七六") => 1,976
'   STRINGNUMBER("千九百七十六") => 1,976
'        STRINGNUMBER("56万3千") => 563,000
'  STRINGNUMBER("参阡伍百萬壱拾") => 35,000,010
'
'REFERENCES
'  Q.“Excelで漢数字を数値に変換する方法を教えてください。”
'  http://q.hatena.ne.jp/1268555767
'
Public Function STRINGNUMBER(ByVal varcl As Variant) As Variant
'''
Dim str As String       'kanji-number string (working variable)
Dim str_org As String   'kanji-number string (original)
'
Dim tmp As String
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''' (0) Initialize the variables
'
tmp = TypeName(varcl)
If DEBUG_KANNUM Then
Call MsgBox("TypeName(varcl)[" & tmp & "]" & vbCrLf & _
"str[" & str & "]")
End If
' Process the argument due to its type.
If TypeName(tmp) = "String" Then
str_org = varcl
Else
str_org = varcl.Value
End If
'Kanji-number string.
str = str_org
If DEBUG_KANNUM Then
Call MsgBox("TypeName(varcl)[" & tmp & "]" & vbCrLf & _
"str[" & str & "]")
End If
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Algorithm:
'
'*Assumption
'  assume that kanji-number string (漢数字文字列) consists of three type of
'  number string: compound units, semi-compound units, and literal
'  numbers.
'
'  compound units (京,兆,億,万) consists of semi-compound units
'  and literal number string.
'
'  semi-compound units (千,百,十) consists of themselves (ex. 千十),
'  and also they sometimes includes literal number string (ex. 3千4百).
'
'  literal number string (〇~九) is able to convert to number (value)
'  directly.
'
'*Way of getting the value of kanji-number string
'  generate the expression from kanji-number string like the following:
'    ((n_1)億)+(n_2)万+(n_3))
'  where n_? is a*1000+b*100+c*10+d, and a-d here indicates 0-9.
'
'  after the step (4), we can obtain the above expression which
'  consists from only numbers, parentheses, product(*), and addition(+).
'
'  and finally, the value is obtained by evaluation of the generated
'  expression at the step (5)
'
'''' (1) Normalize the value.
'  `normalize' means that hankaku, and all characters of
' [0-9],[〇-九] to [0-9].
'
str = StrConv(str, vbNarrow) '半角
'for semi-compound units
str = Replace(str, "拾", "十")
str = Replace(str, "阡", "千")
str = Replace(str, "萬", "万")
'for the literal number strings.
str = Replace(str, "九", "9")
str = Replace(str, "八", "8")
str = Replace(str, "七", "7")
str = Replace(str, "六", "6")
str = Replace(str, "五", "5")
str = Replace(str, "伍", "5")
str = Replace(str, "四", "4")
str = Replace(str, "三", "3")
str = Replace(str, "参", "3")
str = Replace(str, "二", "2")
str = Replace(str, "弐", "2")
str = Replace(str, "一", "1")
str = Replace(str, "壱", "1")
str = Replace(str, "〇", "0")
'''' (2) Structurize for the compound units: 京,兆,億,万.
'
'  (.*)兆+(.*)億+(.*)万+(.*)
'
str = "(" + str
'
str = Replace(str, "京", ")京+(")
str = Replace(str, "兆", ")兆+(")
str = Replace(str, "億", ")億+(")
str = Replace(str, "万", ")万+(")
str = str + ")"
''' (3) Numerize the value
'semi-compound units
str = Replace(str, "千", "*1000+")
str = Replace(str, "百", "* 100+")
str = Replace(str, "十", "*  10+")
'compound units
str = Replace(str, "京", "*10000000000000000+")
str = Replace(str, "兆", "*    1000000000000+")
str = Replace(str, "億", "*        100000000+")
str = Replace(str, "万", "*            10000+")
''' (4) correct the expression of the value.
str = Replace(str, "()", "0")
str = Replace(str, "++", "+")
str = Replace(str, "+)", "+0)")
str = Replace(str, "(*", "(1*")
str = Replace(str, "+*", "+1*")
If DEBUG_KANNUM Then
Call MsgBox("org:" & str_org & vbCrLf & "str:" & str)
End If
''' (5) Eval the generated expression!
STRINGNUMBER = Application.Evaluate(str)
End Function


各構成単位ごとに、丸括弧でくくることが、みそだ。
最終的に、漢数字部分は数字に置き換えられ、数式の形になる。そして、それがApplication.Evaluate()により、数値に変換される。


Have fun!!


2010年8月13日金曜日

VBAのドキュメントの目次一覧

Microsoftのヘルプ機能は、OSのそれにしろOfficeアプリケーションのそれにし
ろ、まったくひどいしろものだ。なにしろ、知りたい機能で検索しても当該ページがで
てこない。
また、このヘルプ・ドキュメントそのものについても、同じ類のことがいえる:
一覧性が非常にひくいのだ──5万数万もの高い金を取りながら、電子マニュア
ルしか存在しないためだ。

最近、立て続けにそんな経験をしたので、ここにExcel2003 のVisual Basic Editor
のヘルプの目次をテキスト形式で一覧にし、示すこととする。これにより、マニュアル全体
を俯瞰することができ、Googleによってインデックス化されれば、検索性も増すであろう。

対象は、Excel2003のVisual Basic Editorのヘルプメニューを開いたときに出て
来るドキュメントだ。これらは開いたときの順番の通りに、項目を挙げている。
本来的には、順番で読むのに適さないが、資料としてこのままとする。

凡例
このテキストでは、■-□-◆の順に、ドキュメントの階層を表す。■がトップレ
ベルだ。
◆A-Zは、必ずしも、AからZまでの項目があるわけではない;実際には歯抜けと
なる項目が存在する。
��?)は、?アイコンを示す。
項目右端の★は、読むべき注目を表す。基礎的な概念について述べている項目に
付した。というのも、資料は必ずしも理解に適した順番で配列されているわけで
はないのだ。階層構造についても、同じことが言える。機会があれば、VBA版
『プログラミング言語C』を書いてみたい。


Visual Basic Editor のヘルプの目次一覧

■Microsoft Excel Visual Basic リファレンス
 □(?)Microsoft Office Excel オブジェクト モデル
 □新機能

  ◆(?)新しいオブジェクト
  ◆(?)新しいプロパティ(アルファベット順)
  ◆(?)新しいプロパティ(オブジェクト順)
  ◆(?)新しいメソッド(アルファベット順)
  ◆(?)新しいメソッド(オブジェクト順)
  ◆(?)新しいイベント
 □プログラミングの概念・・・★
  ◆ブックとワークシート
  ◆セルとセル範囲
  ◆コントロール、ダイアログ、ボックス、フォーム
  ◆イベント、ワークシート関数、図形
  ◆他のアプリケーションを使って作業する
 □コレクション
  ◆A-Z
 □オブジェクト
  ◆A-Z
 □メソッド
  ◆A-Z
 □プロパティ
  ◆A-Z
 □イベント
  ◆A-Z
 □列挙
  ◆(?)Microsoft Office Excel の定数


■Microsoft Visual Basic Documentation
 □Visual Basic ユーザー インターフェース
  ◆コマンド
  ◆キー
  ◆メニュー
  ◆その他
  ◆ショートカット
  ◆タブおよびダイアログ ボックス
  ◆ツールバー
  ◆ウィンドウ
 □Visual Basic プログラミングのヒント
  ◆(?)名前の二重定義の回避
  ◆(?)同じ名前のプロシージャの呼び出し
  ◆(?)Property プロシージャの呼び出し・・・★
  ◆(?)Sub プロシージャと Function プロシージャの呼び出し・・・★
  ◆(?)オブジェクト変数の作成・・・★
  ◆(?)再帰プロシージャの作成・・・★
  ◆(?)配列の宣言・・・★
  ◆(?)定数の宣言・・・★
  ◆(?)変数の宣言・・・★
  ◆(?)プロパティ設定時のコードの実行
  ◆(?)コードのループ
  ◆(?)For...Next ループの高速化
  ◆(?)引数の効率的な引き渡し
  ◆(?)関数からの文字列の取得
  ◆(?)オートメーションの概要
  ◆(?)条件付きコンパイルの概要
  ◆(?)名前付き引数と省略可能な引数の概要
  ◆(?)オブジェクト、プロパティ、メソッド、およびイベントの概要・・・★
  ◆(?)パラメータ配列の概要・・・★
  ◆(?)適用範囲と参照可能範囲の概要・・・★
  ◆(?)変数の有効期間の概要・・・★
  ◆(?)バリアント型 (Variant)の概要・・・★
  ◆(?)Visual Basic の構文の概要・・・★
  ◆(?)配列の使い方・・・★
  ◆(?)定数の使い方・・・★
  ◆(?)データ型の効率的な使い方
  ◆(?)Do...Loop ステートメントの使い方・・・★
  ◆(?)For Each...Next ステートメントの使い方・・・★
  ◆(?)For...Next ステートメントの使い方・・・★
  ◆(?)If...Then...Else ステートメントの使い方・・・★
  ◆(?)コードでのかっこの使い方
  ◆(?)Select Case ステートメントの使い方・・・★
  ◆(?)With ステートメントの使い方・・・★
  ◆(?)Visual Basic の名前付け規則・・・★
  ◆(?)アプリケーション間の連携
  ◆(?)Function プロシージャの記述方法・・・★
  ◆(?)Property プロシージャの記述方法・・・★
  ◆(?)Sub プロシージャの記述方法・・・★
  ◆(?)代入ステートメントの記述方法・・・★
  ◆(?)ファイルへのデータの書き込み・・・★
  ◆(?)宣言ステートメントの記述方法・・・★
  ◆(?)実行可能なステートメントの記述方法
  ◆(?)Visual Basic ステートメントの作成
 □Visual Basic 開発環境
  ◆(?)オブジェクト ライブラリの確認および参照設定の追加
  ◆(?)実行の継続
  ◆(?)ヘルプから使用例をコピーするには
  ◆(?)プロシージャの作成
  ◆(?)コードへの宣言の入力
  ◆(?)特定のステートメントの実行
  ◆(?)プロシージャの検索・・・★
  ◆(?)変数の定義の検索・・・★
  ◆(?)コード内の文字列の置換・・・★
  ◆(?)実行の再開・・・★
  ◆(?)コード内の文字列の検索・・・★
  ◆(?)タイプ ライブラリへの参照設定
  ◆(?)ブレークポイントの設定と解除
  ◆(?)プロジェクト プロパティの設定
  ◆(?)テキスト ファイルのコードへのインポート・・・★
  ◆(?)Visual Basic 環境オプションの設定
  ◆(?)コード ウィンドウの分割
  ◆(?)コード実行の開始・・・★
  ◆(?)コード実行の停止・・・★
  ◆(?)コード実行のトレース・・・★
  ◆(?)構文チェックの設定と解除の切り替え・・・★
  ◆(?)イミディエイト ウィンドウの使用
  ◆(?)オブジェクト ブラウザの使用・・・★
  ◆(?)プロジェクト エクスプローラの使用・・・★
  ◆(?)プロパティ ウィンドウの使用
 □Visual Basic ランゲージ リファレンス
  ◆定数
  ◆データ型
  ◆ディレクティブ
  ◆イベント
  ◆関数
  ◆グループ
  ◆インデックス/一覧
  ◆キーワード
  ◆メソッド
  ◆その他
  ◆オブジェクト
  ◆演算子
  ◆プロパティ
  ◆ステートメント
 □Visual Basic アドイン モデル
  ◆コレクション
  ◆イベント
  ◆メソッド
  ◆オブジェクト
  ◆プロパティ
 □Microsoft Forms リファレンス
  ◆(?)Microsoft Forms オブジェクト モデルの全体像
  ◆Microsoft Forms デザイン リファレンス
  ◆Microsoft Forms 開発者へのヒント
  ◆Microsoft Forms オブジェクト リファレンス


■Microsoft Office Visual Basic リファレンス
 □(?)Microsoft Office オブジェクト モデル
 □新機能
  ◆(?)新しいオブジェクト
  ◆(?)新しいプロパティ (アルファベット順)
  ◆(?)新しいプロパティ (オブジェクト順)
  ◆(?)新しいオブジェクト (アルファベット順)
  ◆(?)新しいオブジェクト (オブジェクト順)
 □プログラミングの概念
  ◆(?)Microsoft Office ソリューション開発者向けのセキュリティ情報
  ◆Office コマンド バーを使用する
  ◆Office アシスタントを使用する
  ◆(?)コレクションからオブジェクトを取得する
  ◆(?)OLE プログラム ID
  ◆(?)MSDN で MODI VBA のリファレンスを検索する
 □コレクション
  ◆A-Z
 □オブジェクト
  ◆A-Z
 □メソッド
  ◆A-Z
 □プロパティ
  ◆A-Z
 □イベント
  ◆A-Z
 □列挙
  ◆(?)Microsoft Office の定数



References
Microsoft Excel 2003; "Visual Basic のヘルプ"; Microsoft, メニュー>ヘルプ(H)