bar_1

contents_map

ラベル 関数 の投稿を表示しています。 すべての投稿を表示
ラベル 関数 の投稿を表示しています。 すべての投稿を表示

2011年3月24日木曜日

[Excel][VBA]COUNTIF関数を複数条件で使うには?

■背景と問題点


以前のエントリ ([EXCEL][VBA] COUNTIF関数で複数条件を扱うには?(OR条件編), 2008.)で、COUNTIF関数によるORで結合された複数条件を扱う方法を紹介した。しかし、この方法だと場合によっては以下のような不具合がある:
  • 条件を満たすセルの数を、二重にカウントしてしまう
  • AND条件については触れていない
また、この問題をググってみても、どうもこれといって、分かりやすい解法が載っているサイトを見つけることはできない(2011年3月現在); 多くのサイトでは、SUMPRODUCT関数、COUNTIFS関数(Excel 2007以降)を使った方法が紹介されているが、この方法では、AND条件しか、指定することができない。
上述の以前のエントリは、本ブログに挙げて以来、継続的にアクセスがある。 COUNTIF関数で複数条件を扱うのに困っている人は、多そうだ。
この問題は、根本的には、COUNTIF関数の第2の引数である検索条件の記述の不自由さに由来するものと、考える。なぜならば(ヘルプ・ドキュメントによれば、検索条件には「式」を書くことが出来ることになっているが、実際には)、検索条件には、「TRUEもしくはFALSEを返す、2項限定の(論理)式」しか、指定 することが出来ないからだ。
そこで、上記の問題点を踏まえ、今回のエントリでは
  • 以前のエントリのように、二重にカウントすることはない
  • ブーリアン演算の指定、すなわち:
    • 条件指定は、AND条件・OR条件どちらも同時に使用可能
    • 条件項目は、いくつでも可能
  • VBAマクロは使用せず、既存の関数のみの単純な方法
であるような、一般化したCOUNTIF関数で複数条件を扱う方法を、紹介する。

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!!


2008年10月14日火曜日

[EXCEL][VBA] COUNTIF関数で複数条件を扱うには?(OR条件編)



2011年3月24日追記:このエントリは、より一般化された方法によって 改善された

COUNTIF関数は、次のような形式で範囲で指定されたセルの中から、条件を満たすセルの個数をカウントするものである:

=COUNTIF(範囲,検索条件)


ここで、「検索条件」とは

計算の対象となるセルを定義する条件を数値、式、セル参照、または文字列で指定します。
たとえば、検索条件は 32、"32"、">32"、"Windows"、または B4 のようになります
(式および文字列を指定する場合は半角の二重引用符 (") で囲む必要があります)。

[Microsoft Excel ヘルプより]


ところで、この検索条件が複数(OR条件)である場合は、どうしたらよいのだろうか?
単純に、次のようにすればいい:

=COUNTIF(範囲1, 検索条件1)+COUNTIF(範囲2, 検索条件2)