アプリ版:「スタンプのみでお礼する」機能のリリースについて

いつもアドバイス頂きありがとうございます。
今回、質問させていただきたいのは、
string型でデーターを取得した文字列に対して
ある文字の文字数がいくつ在るかを取得したいのですが
VBA関数で、そのような関数はあるのでしょうか?


 myDataにstring型の文字列を取得してあります。
その中に「,」(カンマ)が何個存在するかと言う事
を取得したい。

やりたい事として、mydata()の中に2次元配列要素となるデーターを
1次元で仮格納してあり、それをセルに書き出すために2次元
に格納(splitで再格納)しなおしているのですが、データーが変わる
たびに、カンマの数を数えて配列宣言を記入するのが面倒なので、
カンマの数がいくつでも、2次元に再格納できるようにしたいためで
す。
宜しくお願いいたします。

A 回答 (3件)

Split()関数でデータを分割する事が可能ですよ。


Ubound()関数で配列の要素数を取得する事が出来ます。

Split関数で文字列を区切る
http://officetanaka.net/excel/vba/tips/tips62.htm

この回答への補足

すみません。上手く説明が出来ていませんでした。
mydata(1)="あ,い,う,え,お"
mydata(2) ="か,き,く,け,こ"
 ・
 ・
と言う風に、mydata()の中にstringデーターが格納されている
とします。
Option Base 1
Dim OutPutData As Variant
Private Sub データー再格納()
Dim myAry As Variant
  Dim a As Integer, b As Integer
ReDim OutPutData(uboun(mydata), 5)<<<<(*)
For a = LBound(mydata) To UBound(mydata)
myAry = Split(mydata(a), ",")
ReDim Preserve myAry(UBound(myAry) + 1)
For b =LBound(myAry) to UBound(myAry)
OutPutData(a,b) = myAry(b)
Next b
Next a
End Sub

(*)のところの「5」と言う数字をmydata(1)の文字列から取得する関数
と言うものが存在するのでしょうか?
カンマの数が数えられれば、その数プラス1で取得できればと考えた
のですが。
InStr関数をループで用いれば、取得できそうなのですが、特定の
文字をカウントする関数などあればと思い、ご質問させていただきました。

補足日時:2007/11/14 21:01
    • good
    • 0

こんばんは。



言葉で説明されても、私は、あまり理解力がないせいか良く分からないですね。

私自身は、本来は、全体的なものを見て判断したいですね。

2次元配列と1次元配列を行き来するということは、通常はしません。モーグの有名な方は、そういうテクニックを公開していますが、まず、私は、そういうことには直面しません。

通常は、2次元は、最初から、2次元のまま処理するのが普通だと思います。
ただし、CSVなどは、1次元で行ごとに処理します。

String型で入手したものは、

Dim myStr As String
Dim i As Long
Dim j As Long

 myStr = "a,b,c,d,e"
 i = Len(myStr) - Len(Replace(myStr, ",", ""))
 j = UBound(Split(myStr, ","))


このどちらかになりますが、状況によっては、「i」側は、区切り文字が、TextCompare が選べる利点があります。なお、正規表現は、私は、この種類には使いません。理由は、遅いからです。
    • good
    • 0
この回答へのお礼

お返事ありがとうございます。
Len関数とreplace関数でこのような形で得られるのですね。
それと、jの取得の仕方。まるっきり気がつきませんでした。
ありがとうございます。

余談なのですが)
<<通常は、2次元は、最初から、2次元のまま処理するのが普通だと思います。

2次元で格納していくスキルが無いため、無理やり1次元で仮格納して
2次元にしてセルに書き出すやり方をしております。
Find関数を用いて、条件を満たした行の必要な列をカンマで結合して
格納してく方法を用いてます。
最初に
dim mydata(20000, 10) as Variant
と言う形等で、配列数を多く宣言しておけばいいのでしょうが、
このやり方って空のデーターの箱を沢山作ってしまいっているので
なんかもったいないなと思って動的配列で宣言しております。
そうすると、どうしてもRedim Preserveで1次元目を宣言しなおせ
ないので1次元で必要な列データをカンマで結合して格納していって
いるしだいです。
書き出しの時に
WorksheetFunction.Transpose
を上手く使えば2次元の要素を増やしていく格納のやり方とか
出来そうな気がするのですが、自分の頭の中が混乱してくるのと
Transposeの使い方が理解できていないため、
2次元で格納→2次元で書き出し
を行わず
1次元で格納→2次元で書き出し
と言う処理にしております。
余談終了)
wendy02様にはいつもご丁寧なアドバイス、ご回答をいただき誠に
ありがとうございます。

お礼日時:2007/11/14 22:26

こんばんは。



>dim mydata(20000, 10) as Variant
>と言う形等で、配列数を多く宣言しておけばいいのでしょうが、
>このやり方って空のデーターの箱を沢山作ってしまいっているので
>なんかもったいないなと思って動的配列で宣言しております。

私は、他の言語を勉強したときに、なぜ、VBAやVBでは、そういう仕方をしないのかなって思ったことがあります。たぶん、根本的に、VBAやVB は、速度が遅いのが原因ではないか、と思います。それに、Ubound で上限が取れないので、配列の代入時に、カウントして、それを元にする、というしかないわけです。

>Find関数を用いて、条件を満たした行の必要な列をカンマで結合して格納してく方法を用いてます。
似たようにことを、私も以前やったような覚えがあります。

動的な2次元配列が、VBAの上級文法の最後のひとつに入りますね。上級とはいっても、必要不可欠です。

Excelでは、有名な「バブルソート・アルゴリズム」をExcelシートに応用するという命題みたいなものがあります。一応、掲示板の常連さんは、みなさん、一度は勉強していると思います。(偉そうな言い方で申し訳ないのですが。)

とはいえ、なぜ、Excelにとって、2次元配列がややこしいかというと、お気づきだと思いますが、排出の仕方が、縦横逆になるからなのです。For Each ~ in myRange でやってみると、左から右へと動いていくのが分かりますが、配列は、添え字の1次側から順に排出てしていきます。ちょっと不思議ですよね。たぶん、これは、メモリの確保の仕方から来るものだと思います。

また、2次元の場合は、二次側を、動的配列にします。一次側は固定されます。

Redim Preserve myData(固定値, カウンター)

それから、

WorksheetFunction.Transpose これは、1次元に限ります。ただ、こういうレベルというのは、このサンプルで見たとおり、そのままですから、

Worksheets("Sheet2").Range("A1"). _
 Resize(UBound(myData, 1) + 1, UBound(myData, 2) + 1).Value = myData()

で、形どおりに貼り付けが可能です。
-----------------------------------------------------------
先ほどからずっと、動的2次元配列のサンプルが思いつきませんので、#1さんの補足に書かれたものを元に書いてみました。一般的には、配列に配列を入れるようなことはしないで、そのまま、1行ずつ排出します。

なお、余計なことかもしれませんが、私個人は、
 Option Base 1
を使わないことにしています。将来的になくなるということもありますが、今回のコードの場合は、逆にややこしくなっているようです。配列は、0からスタートと考えていたほうが安全です。

ためしに、入れ替えてみました。以下のコードのように、Max で、上限を取らざるを得ません。それ以外に、列幅の上限を知る方法はありません。通常は、一行ずつ処理するというのが一般的です。ここまですると、ややこしいです。


'Option Explicit
Option Base 1
Sub ArrayTest()
  Dim buf As Variant
  Dim Max As Integer
  Dim i As Long
  Dim j As Long
  Dim k As Long
  Dim v As Variant
  Dim myData(10)
  Dim myAray() As Variant
  Dim OutPutData() As Variant
  
  myData(1) = "あ,い,う,え,お" 'ここの列数は不明ゆえ
  myData(2) = "か,き,く,け,こ" 'Max を取る
  myData(3) = "さ,し,す,せ,そ"
  myData(4) = "た,ち,つ,て,と"
  
  For i = 1 To UBound(myData)
  If myData(i) = Empty Then Exit For
    buf = Split(myData(i), ",")
    ReDim Preserve myAray(1, i) '動的2次元配列
    '配列をチェックしないと、エラーが出る
    If IsArray(buf) Then
    If (UBound(buf) + 1) > Max Then Max = (UBound(buf) + 1)
    End If
    myAray(1, i) = buf
  Next i
  ReDim OutPutData(i - 1, Max)
  For j = 1 To i - 1
    For Each v In myAray(1, j)
      k = k + 1
      OutPutData(j, k) = v
    Next v
    k = 0
  Next j
  Range("A1").Resize(UBound(OutPutData(), 1), UBound(OutPutData(), 2)).Value _
   = OutPutData()
End Sub


何かのヒントになった幸いです。
    • good
    • 0
この回答へのお礼

お返事ありがとうございます。
このような形でテストサンプルコードまで
ご用意頂き誠にありがとうございます。
VBAを勉強させていただくに当たり、このような
サンプルコード等を頂け誠にありがとうございます。
こういった形でコード読んでいきますと、自分の
理解できていなかった事や、コードの記述テクニック等
色々な面で勉強させていただけるので、とても
助かります。おかげさまでVBAを勉強始めてから
仕事の能率がかなりはかどっているしだいです。
誠にありがとうございます。
今後ともご質問させていただく機会はあると思いますが
宜しくお願いいたします。

お礼日時:2007/11/16 21:46

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!