• ベストアンサー

エクセルのカウント

宜しくお願いします。 あるデータをCSV形式で抽出したのですが、以下のような状態になっています。 / A B 1 a Windows 2 a Linux 3 a Sun 4 b Windows 5 b Sun 6 c linux 7 c Sun 8 d Windows 12345678は行 ABは列になります。 ここで抽出したいのはA1:A8の間に何種類の文字があるかです。 この場合は、abcdの4種類なので「4」という数値が出て欲しいのです。 データ件数が13000行ほどあるので関数やVBでどうにかならないかなと思い、質問しました。 宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • mu2011
  • ベストアンサー率38% (1910/4994)
回答No.2

以下の関数(配列)で如何でしょうか。 {=SUM(1/COUNTIF(A1:A1300,A1:A1300))} { と } は実際には入力する必要は無く、式の入力の最後にShiftキーとCtrlキーの両方を「押しながら」Enterキーを押して下さい。

ark_kiss
質問者

お礼

回答ありがとうございます。 No.1の方と同じ数値が出ました。 ただし、実は一部数値が13000件で、全データをCSVにエクスポートした結果、34000件に膨れ上がりました。 質問文ではB列までしかありませんが、実際データは29列まであったり・・・。 検索結果が出るまで、こちらも数分かかってしまうので、ハングしてしまわないか不安でした。 ありがとうございました。

その他の回答 (5)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

まだ、オープンされているようですね。 13000行ですと、Excelの Version(2000以下) では、配列にエラーが使えない時があります。したがって、Version を示されないときは、VBAがベストだと思います。BLUEPIXYさんが、Dictionary を使っていますので、こちらは、ユニーク・アルゴリズムを使います。 該当する列を選択してから、マクロを起動します。 '<標準モジュール登録> Option Explicit Sub UniqCount() Dim N As Long Dim i As Long, j As Long Dim S As Long Dim Flg As Boolean Dim cnt As Long Dim myData() Dim a()   '該当する列を選択してから、マクロを起動する   N = Range(Cells(1, ActiveCell.Column), _    Cells(65536, ActiveCell.Column).End(xlUp)).Count   ReDim myData(1 To N)   For i = 1 To N    myData(i) = Cells(i, 1) '先頭はフィールド名ではないとします   Next i   Flg = False   ReDim a(1 To N)   i = 0   For i = 1 To N    Flg = True 'sentinel    For j = 1 To S      If a(j) = myData(i) Then       Flg = False       Exit For      End If    Next j    If Flg = True Then      S = S + 1      a(S) = myData(i)    End If   Next i   For i = 1 To N    If a(i) <> Empty Then      cnt = cnt + 1    Else      Exit For    End If   Next i   MsgBox cnt End Sub

ark_kiss
質問者

お礼

オープンし続けて申し訳ありません。 こう言ってしまうのは、大変恐縮なのですが・・・。 いろんな関数、VBによる結果を比類して、抽出された数値の精度を上げようかと思っていました。 皆様が提案された関数やロジックによって、特定の結果が出ることが確認されました。 この場をお借りして、皆様にお礼を申し上げます。 ちなみに、34000件から抽出された数値は4896です。 ありがとうございました。

  • maruru01
  • ベストアンサー率51% (1179/2272)
回答No.5

こんにちは。maruru01です。 >データ件数が13000行ほどあるので ということだと、SUMPRODUCTやSUMを使用した数式は、配列数式なので重くなるかも知れませんね。 重くなる場合は、No.3の方のようにユーザー定義関数を使うか、作業列を使用した方が無難かも知れません。 以下、作業列を使用する方法の1つです。 仮に作業列をC列とすると、C1に、 =COUNTIF($A$1:A1,A1) と入力して、下の行へコピーします。 そうしたら、 =COUNTIF(C:C,1) でデータ種類数が出ます。 作業列は離れていても構わないし、非表示にしておいてもいいですよ。

ark_kiss
質問者

お礼

回答ありがとうございます。 No.1-2様と同様の数値が出ました。 ただし、やはり数が34000件ともなると、手動の部分(コピー)で時間をとられてしまいます。 作業列は、仰るとおり離れた場所での作業となりました。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.4

#3です あと、もう一つ注意を忘れてました。 COUNTIFによる方法は、Aとaを区別しませんが kindは、区別します。 これは、利点でもあり欠点でもあります。

ark_kiss
質問者

お礼

区別に関しては・・・。 公表してしまうと、A列に出てくるデータはネットワーク監視用のサーバから引き抜いてきた、クライアントのドメインを絡めたフルコンピュータ名です。 その為、大小文字を区別しなくても大丈夫です。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

前にOKWebで見た方法は =SUMPRODUCT(1/COUNTIF(A1:A8,A1:A8)) だけど、1/n*nで誤差がでたりしないのか不安だから 関数を作ってみました。 =kind(A1:A8) のように使います この方法の利点は、途中に空白があっても(無視するので)良いこと ---------------------------------------------------- Public Function kind(r As Range) '指定された範囲のデータの種類を数える Dim x As Range Dim aDic Set aDic = CreateObject("Scripting.Dictionary") For Each x In r If (Not x.Value = Empty) And (Not aDic.Exists(x.Value)) Then '中身がない、重複する時は登録しない aDic.Add x.Value, x.Value End If Next kind = aDic.Count End Function

ark_kiss
質問者

お礼

回答ありがとうございます。 自分で関数を作るというのは盲点でした。 BottunによってVBを動かして抽出するか、通常の関数だけとしか考えていなかったです。 参考になります、ありがとうございます。

  • mshr1962
  • ベストアンサー率39% (7417/18945)
回答No.1

=SUMPRODUCT(1/COUNTIF(A1:A13000,A1:A13000))

ark_kiss
質問者

お礼

回答ありがとうございます。 No.2の方と同じ数値が出ました。 ただし、実は一部数値が13000件で、全データをCSVにエクスポートした結果、34000件に膨れ上がりました。 質問文ではB列までしかありませんが、実際データは29列まであったり・・・。 検索結果が出るまで、数分かかってしまうので、ハングしてしまわないか不安でした。 ありがとうございました。

関連するQ&A

専門家に質問してみよう