No.7ベストアンサー
- 回答日時:
私が#5で書いたものでは通じていないようなので、もう一度まとめさせていただきました。
この関数の原型は、LotusグループからIBMにノウハウが移動したものを、マイクロソフトの開発チームがあれこれと考えて、手を加えたものだとは思います。その仕組みを知りたいというなら、C言語や、せめてVBAで同じ表現ができるように作ってみて、ある程度の概要が分かるもので、それをワークシート上では、表面的なものでしか分からないと思います。
また、私は、その中身を、深く追求するような興味はありませんでしたが、少々、このままでは、治まらないので、VBAで作ってみました。文字比較とは言っても、文字コードではなく、バイナリ比較(binary compare[ワークシート上の制約あり])になっているだけです。しかし、数値と文字の比較に関して、別途に出てくるというようなので、数値のcountを別々に取りました。そういう仕様で振り分けているのだというしかありません。
もっと複雑なものを想像していましたが、どうやら、その結果は偶然の産物のようです。意図して作られたものではないようです。まだ、修正点はあるかもしれませんが、一応、仕様は分かったような気がします。
興味のある方はどうぞ試してみてください。
'//標準モジュール
'//
Public Function mCountIf(arg1 As Range, arg2 As Variant)
Dim bln As Boolean
Dim fml As String
Dim cnt As Long, cnt2 As Long, cnt3 As Long
Dim expr As String
Dim ope As String
Dim c As Variant
arg2 = Trim(arg2)
Select Case True
Case arg2 Like "=>*"
mCountIf = 0: Exit Function
Case arg2 Like "=<*"
mCountIf = 0: Exit Function
Case arg2 Like ">=*"
ope = ">=": expr = Mid(arg2, 3)
Case arg2 Like "<=*"
ope = "<=": expr = Mid(arg2, 3)
Case arg2 Like "<>*"
ope = "<>": expr = Mid(arg2, 3)
Case arg2 Like ">*"
ope = ">": expr = Mid(arg2, 2)
Case arg2 Like "<*"
ope = "<": expr = Mid(arg2, 2)
Case arg2 Like "=*"
ope = "=": expr = Mid(arg2, 2)
Case Else
ope = "=": expr = arg2
End Select
For Each c In arg1
If VarType(c) = vbString Then
fml = "=""" & c.Value & """" & ope & """" & expr & """"
If Evaluate(fml) Then
cnt = cnt + 1
End If
ElseIf VarType(c) = vbDouble Then
fml = "=""" & c.Value & """" & ope & """" & expr & """"
If Evaluate(fml) Then
cnt2 = cnt2 + 1
End If
Else
cnt3 = 0
End If
Next c
Select Case True
Case VarType(expr) = vbString And expr <> "" And Not IsNumeric(expr)
mCountIf = cnt
Case IsNumeric(expr)
mCountIf = cnt2
Case expr = ""
mCountIf = cnt3
End Select
End Function
'//
誠に申し訳ないのですが、私の知識、理解力では、具体的仕様が理解できていません。
VBAで試す?のを 具体的にどうするのかがわかりません。
mCountIfの関数で、arg1,arg2にいろいろ入れてみただけです。0が返れば≠、1が返れば=のようですが、arg1=123,arg2='123 arg1='123,arg2=123 などでは結果が変わります。
セルの式ではなく、セルの値を評価しているのはわかりました。
セルの値がnullだと(arg1,arg2でも、)、0が返るようです。
文字コード比較ではないから、aAとAaは同値になることもわかりました。
arg2の文字列が”>=文字列”や"<>文字列"のような場合は、比較演算子と文字列に分けて、true,falseの判定をしているというのはわかりました。
大小判定を、何かの方法で、演算子の結果、関数の結果やこのmCountIfの関数のarg1,arg2で、true/falseとやっているから、その結果は、ただExcelシートをながめても、ピンとは来ないというだけのことはわかりました。
その延長線上で、「"<=" & $A$4:$A$8」も、セル位置に合わせ"<=(セル位置のA列のセルの値)"に置換させて、さらに処理しているので、
=mCountIf($I$12:$I$30,"<="&$I$12:$I$30)も計算できるということもわかりました。
arg2に、
① '76のような文字がなく、7、78、789のような数値しかない場合は、通常の文字列とは別系統の文字列として順位評価すること、
② '76のような文字と8のような数値があると、共に数字系の文字列としての順位をつけること、
('76のような文字と8のような数値を文字列とみなした系列としての順位がつく)
③ '88、'32のような文字列だけだと、それらの数字だけの文字列は評価の対象にされないこと、
などが、mCountIf(であって、CountIf(と類似しているらしいことはわかりました。
VBAコードがわからないので、わからないことは前と同じですが、動作の理解は進みました。
文字列、数字列、数値が混在したママで、CountIf(やmCountIf(を使うと、どのように順位が振られるのかのが、おおよそ理解できた気がします。
ありがとうございました。
No.6
- 回答日時:
確かに、No.4の回答のように
1.セル B4 の式 =COUNTIF($A$4:$A$8,"<="&$A$4:$A$8) をドラッグコピーすると
' =COUNTIF($A$4:$A$8,"<="&C4) のドラッグコピーは等しいですね。
配列数式の際にそうしたことが起きるのと似ていると思います。
No.1の回答と回答に対するコメントをやってみると、確かに、何が起きているのかが、私にはわかりません。単純に文字列コードをベースにしているのではなさそうです。(No.4さんのを参考にしました)
No.3の回答は、根気不足だけではなく、内容が難しくて、「★だから、B6に入力した"<=" & $A$4:$A$8という部分は実際は "<=" & $A$6となるのわかる」とは私にはならないです。
文字列と数値のことも、「★最初が要するに最初2文字までに来る文字で、不等号の種類を判別して、それを除いたやつをmaStringに代入して pFormatter(多分nullptrではない)がnullptrでないときは、数値等として解釈可能であるか調べ、解釈可能であったときは、数値比較、それ以外は文字列比較、ということ」というのも理解できないですが、添付画像のように、C12:C26、E12:E26、I12:I26 となることを説明できているのかさえも、私にはわからないです。
No.5
- 回答日時:
こんにちは。
=COUNTIF($A$4:$A$8,"<=" & $A$4:$A$8)
これは、一種の配列計算ですね。どこが配列かというと、"<=" の後は、本来、数字か文字列なのですが、ここに配列になっているわけで、これは、制作側の非公開の隠しコマンドだと思います。マニュアルには載っていませんから。
理由は分かりません、制作側の気まぐれだと思います。
制作上、配列の引数をエラーにしても良かったのではないかと思います。
配列式ではあるのですが、この数式表現は別の配列数式にも書き換えられます。
B4: =SUMPRODUCT(($A$4:$A$8<=$A4)*1) 下にドラッグコピー
添付図をご覧になってください。
仕組みは、
B4:=($A4<=B$3)*1
B5:=($A5<=B$3)*1
= ("hg" <= "hg")*1
=1
= ("hhggfs" <= "hg")*1
=0
となっています。
9行目は、SUM合計で作られています。
たんなる文字の比較ですが、COUNTIF <= は、等しいか、それ以上(文字コード)なら、1と数えることになっています。
なお、必ず、数値 <文字列です。もし、比較するなら、数値を文字列に変えて、文字列と比較しなければなりません。
567 <"123" という等式が成り立ちます。単純な比較する時は、文字列と数値とは混在はできません。
No.4
- 回答日時:
こういう不思議な現象に遭遇した場合の私の常套手段は推理に基づいて実験することです。
推理のネタは文字コードです。
1.式 =$A$4:$A$8 を入力したセル C4 を下方にオートフィル
 ̄ ̄その結果を添付図の列C(橙色)です。
もうお分かりと思うけど、貴方が示したセル B4 の式
=COUNTIF($A$4:$A$8,"<="&$A$4:$A$8)
は
=COUNTIF($A$4:$A$8,"<="&C4)
と同じことで、貴方の添付図に示した他のセルの式もその「同じ」ものをオートフィルしたものに等しいですね。
先を急ぎませう。
2.式 =CODE(MID($A4,COLUMN(A4),1))*1 を入力したセル D4 を右隣および
 ̄ ̄下方にオートフィル(黄色)
3.式 =(D4&TEXT(E4,"000"))*1 を入力したセル F4 を下方にオートフィル(薄
 ̄ ̄青色)
4.式 =COUNTIF(F$4:F$8,"<="&F4) を入力したセル G4 を下方にオートフィ
 ̄ ̄ル(赤地に白抜数値)
私の推理、当たっているかしらン?
以上、此れでも、ゴチャゴチャ講釈は出来るだけ省いたつもり。
No.3
- 回答日時:
部分点狙いの回答。
(【なかなか本題に行かない】)満足してもらえるかわからないが、根気よく読んでもらえれば理解はしてもらえるだろう。
★Excelのソースコードは当然配布されないのでわからないが、LibreOfficeもある程度追従するだろう、ということを飲み込んでもらえると嬉しいなぁ。ここを妥協してもらえないとあと全部無駄になるからなあ
* 逆ポーランド記法を用いた電卓の実装方法
https://knowledge.sakura.ad.jp/220/
これを最後まで読んだ上で。
>高級な言語ではコンパイルといえばもう少し複雑な手法と手順で構文解析を行います。
* 演算子と関数は本来同じもの!シンタックスシュガー。(ただし、言語の文法が中置記法でしか書けないものだったりするだけ)。
オーバーロードの概念がある言語の場合、演算子オーバーロードの説明を読んでおくのも吉。
* BNF記法について
http://www.atmarkit.co.jp/fxml/ddd/ddd004/ddd004 …
** 直接関係ないけど、練習としてJavaの仕様とか見ると面白い。上記BNFがわかっていればそれほど苦労しないはず。
https://docs.oracle.com/javase/specs/jls/se9/htm …
再帰的に定義されている。
StatementExpression(式文) => Assignment(代入) => Expression(式) => AssignmentExpression(代入式)
=> ConditionalExpression 以下略と辿っていくとこんなのにぶち当たる。
15.18. Additive Operators
AdditiveExpression:
MultiplicativeExpression
AdditiveExpression + MultiplicativeExpression
AdditiveExpression - MultiplicativeExpression
15.17. Multiplicative Operators
MultiplicativeExpression:
UnaryExpression
MultiplicativeExpression * UnaryExpression
MultiplicativeExpression / UnaryExpression
MultiplicativeExpression % UnaryExpression
ところで、15.2にはこんな記述がある。
Precedence among operators is managed by a hierarchy of grammar productions. The lowest precedence operator is the arrow of a lambda expression (->), followed by the assignment operators. Thus, all expressions are syntactically included in the LambdaExpression and AssignmentExpression nonterminals:
演算子の優先順位は文法生成規則(BNFや上記Javaの文法で見てきた各定義のことね!)の階層構造による。最も優先度の低い演算子はラムダ式のアロー演算子であり、代入演算子が続く。こういう感じで全ての式は文法上LamdaExressionかAssignmentExpressionの非終端記号に含まれる。
というわけで。【少なくともJavaにおいては、掛け算の方が足し算よりも優先される】のでした。
* 暗黙の型変換
https://asciidwango.github.io/js-primer/basic/im …
* 実際のLibreOfficeの実装は?
ScCompiler関連クラスが主にユーザーが入力した、中置記法を含む式を逆ポーランド記法に変換している。以下例
https://opengrok.libreoffice.org/xref/core/formu …
ScInterpreterクラスが主に逆ポーランド記法になった式(実際にはTokenArray型)を評価している、
練習として余りを求める関数Modを読んでみよう。
【スタックから引数を逆順に取り出していること】を忘れずに。まぁ最初は引数の数を1バイト乗っけてあってGetByte()で取ってるみたいだけど。
ScInterpreter::GetDouble()はスタックの一番上の要素を取り出し、【double型に型変換して返す】。GetString()なんかは、スタックの一番上の要素をStringに変換して返す。GetStackType()なんかは情報見るだけでスタック弄らないみたいだけど。ちなみにScInterpreter::PopString()は型変換しない。欲しい型のデータじゃない場合はエラーになる。
https://opengrok.libreoffice.org/xref/core/sc/so …
そうScInterpreter::ScMod()側で型変換している。結果としてエンドユーザー側からは暗黙の型変換に見える。
本題だ。文字列連結演算子&は、ScInterpreter::ScAmpersand()で当然
ScInterpreter::GetString()を呼んでいる。
https://opengrok.libreoffice.org/xref/core/sc/so …
A1みたいなやつはsvSingleRef,A1:A2みたいなやつはSvDoubleRefって型だ。
ScInterpreter::DoubleRefToPosSingleRef( aRange, aAdr )って奴が呼ばれるみたいだからちょっと定義読んでみようかな。各引数は参照渡しだ。行列(Matrix)周りは全部読み飛ばしてっと。
https://opengrok.libreoffice.org/xref/core/sc/so …
あ、aPosは式を入力したセルで、Tab()はシート番号を返すんだよねー。
★だから、B6に入力した"<=" & $A$4:$A$8という部分は実際は "<=" & $A$6となるのわかるだろうか?同じA列で、4 <= 6 かつ 6 <= 8だからね。いや正直絶対参照か相対参照かはちゃんと調べてなくて自信ないんだけど(汗)
さてこの調子で、エンドユーザー視点の使い方を思い出しながら、ScInterpreter::ScCountIf()も読んでみようか(にっこり)
https://opengrok.libreoffice.org/xref/core/sc/so …
まず最後の引数は条件だったね。
Value(数値等)の場合その値をfValに代入して、bIsStringがfalseになり…
可変長引数絡みでwhileでくくっている部分があるのを臨機応変に解釈。ここはそのままSvDoubleRefを変換せず扱う、っと。
5580行周りで、数値比較であることを確認して5595行あたりの分岐で行列とそれ以外に応じて分岐しているけどどっちにしても要素列挙しながら数え上げているだろうことは同じ。、
最後の引数が文字列だったら…? ScQueryParamBase::FillInExcelSyntaxが呼ばれているな…。
https://opengrok.libreoffice.org/xref/core/sc/so …
copyメソッドは、文字列の一部を取ってくるメソッドとして読むと…
★最初が要するに最初2文字までに来る文字で、不等号の種類を判別して、それを除いたやつをmaStringに代入して
pFormatter(多分nullptrではない)がnullptrでないときは、数値等として解釈可能であるか調べ、解釈可能であったときは、数値比較、それ以外は文字列比較、ということだ。
だから例えば、
=COUNTIF(A1:A2,">3")
は数値3との比較だが、B1に3が入っていたとして
=COUNTIF(A1:A2,">B1")であったときには
"B1"という文字列との比較になる、ということだ。
★手元のLibreOfficeの環境だと
=COUNTIF(A1:A2,">2017-01-01")は日付=>数値比較になったりする。面倒くさいから調査してないだけだが、「どんな文字列が数値比較になるか」をちゃんと把握しておく必要がありそう。
注意事項は★に記しておいた。ちゃんと把握するのはそれ自体難しい。
No.2
- 回答日時:
No.1です。
>データはA$3:A$20 (文字のセルと、数値のセルの混在です)
>しかし、順位は正しくないです。 異なる値に同順位がでます。
具体的にどのようなデータが入っているのか判らないのですが、
文字コードが基準になっていると思います。
ただ気を付けなければならないのは
「文字列」セルと「数値セル」が混在している場合は思ったような並び替えができないことがあります。
私にはサイトで検索してもその原因ははっきり判りません。
前回投降した数式は文字列の並び替えより数値セル(RANK関数)の同順位を回避するために使うコトがほとんどです。
(文字列の並び替えで使ったコトはないと思います)
↓のサイトが参考にならないでしょうか?
http://officetanaka.net/excel/function/tips/tips …
的確な回答でなくてごめんなさい。m(_ _)m
No.1
- 回答日時:
こんばんは!
個人的にそのような使い方をしたことはありませんが、
お示しの使い方は少し裏技的な使い方になります。
式の説明となると当方もなぜそうなるかは、はっきり説明できません。
仮に一気に別列に小さい順(昇順)に表示する場合
=INDEX(A$4:A$8,MATCH(ROW(A1),INDEX(COUNTIF(A$4:A$8,"<="&A$4:A$8),),))
という数式を入れフィルハンドルで下へコピーすると
お示しの画像のB列の昇順にA列データが表示されるはずです。
自分であれば、単に順位付けだけならそんな難しい使い方をせず
B4セルに
=COUNTIF(A$4:A$8,"<="&A4)
という数式を入れ下へフィル&コピーします。
(数値データのRANK関数と同じコトですかね)
※ 仮に同順位(重複データ)があり、順位の差をつけたい場合は
数値データでもRANK関数を使わず
=COUNTIF(A$4:A$8,"<"&A4)+COUNTIF(A$4:A4,A4)
という数式を入れフィル&コピーで同順位なしの順位が返ります。
(同順位の場合は上側のデータが上位となる)
尚、降順の場合は不等号の向きを変えます。
※ 式の説明ではなく、当方個人的な使い方だけでごめんなさい。m(_ _)m
回答ありがとうございます。
画像を貼り付けられないのですが、次の式を入れて見ました。
データはA$3:A$20 (文字のセルと、数値のセルの混在です)
しかし、順位は正しくないです。 異なる値に同順位がでます。
式はD3のセルに =COUNTIF(A$3:A$20,"<"&A3)+COUNTIF(A$3:A4,A3) (フィルコピー)
並べ替えもおかしいです。 出てこない(抜けてしまう)データが多発します。
式はC3のセルに =INDEX(A$3:A$20,MATCH(ROW(A1),INDEX(COUNTIF(A$3:A$20,"<="&A$3:A$20),),)) (フィルコピー)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセルの数式について教えてください。 2 2023/03/04 09:54
- Excel(エクセル) エクセルの数式について教えてください。 2 2023/02/18 11:30
- Excel(エクセル) 【エクセル】COUNTIFの検索条件が可変する数字の場合の数式 1 2022/09/27 15:34
- Visual Basic(VBA) エクセルマクロでアニメを作る方法を教えてください。 1 2023/02/07 14:27
- Excel(エクセル) 表示形式、文字列セル(列)に数式を入力するには マクロ 1 2022/09/18 10:53
- Excel(エクセル) エクセルのマクロについて教えてください。 2 2023/02/11 14:50
- Excel(エクセル) 出勤簿の土、日、休日に色付けできない 2 2022/08/04 20:10
- Excel(エクセル) エクセル 関数について質問です。 2 2022/10/03 11:14
- Excel(エクセル) Countifよりも早く重複数をカウントする方法ありますか? 18 2022/07/04 13:39
- Excel(エクセル) countif関数について質問 4 2022/06/14 12:11
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【関数】スペースがいくつ入っ...
-
西暦や和暦の表示をyyyymmdd表...
-
【Microsoft Office Excel Comp...
-
Excelはなんで先頭の0を消すん...
-
Excelのセルを飛ばして入力する
-
別シートからの文字を変更
-
エクセルの行の抽出について質...
-
Excelのオートフィル
-
Excel 2019 のピボットテーブル...
-
スプレッドシート クエリ関数 1...
-
excelの不要な行の削除ができな...
-
Excel初心者です。 詳しい方、...
-
【Excel】セル内の時間帯が特定...
-
Excel初心者です。 詳しい方、...
-
EXACT関数とIF関数の組み合わせ...
-
Excelのグラフ軸について
-
スマートな関数を教えて下さい。
-
Excelで全角を半角にしたいので...
-
【マクロ】エクセルにかいてあ...
-
Excel:一部のフォントでセルの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ファイル内にある数字の出現回...
-
Excel関数の先頭に「@」が入っ...
-
エクセルの気味悪い不思議
-
Excel VBAで、実行時にsheet上...
-
表示されている人数だけを数え...
-
他人が作ったマクロの理解
-
Excelの関数について質問です。
-
Excel 集計表
-
エクセル 日時の計算式について
-
Excelの関数に関して質問です。...
-
エクセル:セル内の文字列の下...
-
絞り込み検索
-
エクセルの関数で
-
エクセルの書式設定について教...
-
余分なEXCELファイルに印刷され...
-
VBA 同一シート内での転記の仕方
-
長期休みの関数はありますか
-
Excelの空のセル
-
エクセルで入力してある文を別...
-
Excelのマクロで、セルを結合し...
おすすめ情報