エクセル雑感
VBAのString型の最大文字数について

ExcelマクロVBAとエクセル関数についての私的雑感
最終更新日:2020-06-21

VBAのString型の最大文字数について


ツイッターで出したVBAのお題です。
String型はVBAリファレンスでは、「可変長文字列は、最大で約 20 億 (2^31) 文字を格納できます。」と書かれています。
これについて、本当は何文字まではいるのかについての問題です。


お題のツイート

https://twitter.com/yamaoka_ss/status/1273898445015670784

【VBAどうでも良いクイズ】
String型はVBAリファレンスでは、
「可変長文字列は、最大で約 20 億 (2^31) 文字を格納できます。」
と書かれています。
「約」ってなんだ、この際はっきりさせようじゃないか。

VBA マクロ String型 最大文字数


普通の問題だと、実際に実行してみると直ぐに分かってしまってつまらないのだが、
むしろこれは実際に確かめて回答してもらって良い問題です。
そもそもどうやって確認するか、、、

ここには二つの教訓がある。
・書かれていることを妄信してはいけない。
・「約」と書く場合はそれなりの事情がある。
エクセルやVBAに限ったことではないですね。

ツイッターで頂いたリプライから

頂いたリプの中で、特に参考に読んでいただきたいツイートを載せておきます。

https://twitter.com/Z1000R_LR/status/1273981198612566019

https://twitter.com/hoehoe1234/status/1273991137682837504

解説のツイート

https://twitter.com/yamaoka_ss/status/1273986312131842048

答えは、Excelが64bitなら、2,147,483,635です。
しかし、32bitの場合は数億台でエラーになります。(数値ははっきりせず)

21億までの答えが多いのは当然だと思うのですが、
「とことんいける」が次いで多いのが頼もしい。
とことん行きたいですよね。
明日時間があれば可能な範囲で説明します。


では順に説明していきます。
「最大で約20億(2^31)文字」これを読んでピンきた方は相当にお詳しいひとですね。
この20億(2^31)という数値は、Long型の数値の最大数になります。
ではなぜ、String型の最大文字数がLong型の最大数と関係があるのでしょうか。
変数宣言のDimとデータ型|VBA入門
マクロVBA入門者が、まず最初につまずくのが、このDimで変数を宣言することでしょう。変数とは、数値や文字列など(すなわちデータ)を一時的に格納する入れ物 と良く説明されますが、まずはこの考えで良いでしょう。この入れ物には、いろいろなタイプの入れ物があります。

実際にVBAで確かめてみましょう。
文字列を大量に作成する関数には、String関数とSpace関数があります。
関数名の後ろに$をつけると戻り値の型がString型になります。
簡単なところで、Space$関数で検証してみましょう。
以下の検証は64BitのExcelになります。
32bitについては最後に説明します。
Space関数|VBA関数
Space関数は、指定した数のスペースからなる文字列を返す文字列処理関数です、バリアント型(内部処理形式StringのVariant)の値を返します。Space関数 Space(number) number スペースの数を指定します。この引数は必ず指定します。
String関数|VBA関数
String関数は、指定した文字コードの示す文字または文字列の先頭文字を、指定した文字数だけ並べた文字列を返す文字列処理関数です、バリアント型(内部処理形式StringのVariant)の値を返します。String関数 tring(number,character) number 必ず指定します 長整数型(Long)の値を指定します。

まずはイミディエイトで、
?Space(2 ^ 31)
※^は64bitのVBAではLongLongの型文字になるので^の前に空白が必要です。
「オーバーフローしました。」
プロシージャーを書いて1から順に確認してみましょう。
Dim str As String
Dim i As Long
  For i = 1 To 31
str = Space$(2 ^ i)
Next

VBA マクロ String型 最大文字数


エラーになった時点の変数iは30です。
2 ^ 30
これは1073741824
20億の半分でもエラーになってしまいました。
これはSpace関数の制限です。
2 ^ 30 -1
ここまでがSpace関数の限界になっています。
これはString関数も同じです。

VBA マクロ String型 最大文字数


関数の制限であって、String型変数の限界ではありません。
そこで、Space$(2 ^ 30 -1)を&でつなげてみましょう。
str = Space$(2 ^ 30 -1) & Space$(2 ^ 30 -1)
これはエラーになります。
確認には処理時間がかかるので目星をつけて、
2 ^ 31
この少し下の数値から確認してみましょう。


&で1文字ずつ足していったりすると、これはもうVBAが終わらなくなりますので、気を付けてVBAを書きます。
Dim str As String
Dim i As Long
For i = 20 To 1 Step -1
  str = Space(2 ^ 30 - 1) & Space(2 ^ 30 - i)
  Debug.Print Len(str)
Next
すこし時間がかかりますがエラーになります。
2147483635
ここが限界です。

VBA マクロ String型 最大文字数
遅い文字列結合を最速処理する方法について
VBAは遅い… よく聞くことですが、確かに普通にコード記述しているととても遅いことがあります、その代表の一つに、文字列結合があります、文字列結合を最速処理する方法について解説します。そもそも文字列結合は、なぜ遅いのか、String型(可変長文字列)についての基礎知識が必要です。

この数値(2147483635)は、いったいどんな数値なのでしょうか。
「最大で約20億(2^31)文字」でしたが、
2^31=2147483648
Longの最大数は、
2^31-1=2147483647
これよりも、もう少しだけ小さい数値になっています。


String型変数のアドレスには、実際の文字列が入っているメモリアドレスが入っています。
確認するにはVarPtr関数とStrPtr関数を使います。
実際の文字列があるアドレスの直前には4バイトの文字列長部分があり、文字列の直後には2バイトの終端があります。
https://excel-ubara.com/excelvba4/EXCEL_VBA_422.html
VBAにおける変数のメモリアドレスについて
VBA開発においてメモリアドレスを気にすることはほとんど無いと思います。気になる場合があるとしたら、・String変数の処理が遅い ・Variant変数の処理が遅い ・ByRef,ByValの違い ・WindowsAPI使用時 このような場合に多少は気になる事があるくらいではないでしょうか。

4バイトの文字列長、これはLong型の数値です。
つまりString型の最大文字数は、
Long型の最大数、
2^31-1=2147483647
ここから終端の2バイトを引いた、
2147483645
これがString型の最大文字数になります。
以上が64bitの場合のString型の最大文字数です。


では32bitの場合はどうなるでしょうか。
32bitの制限でメモリは4GB(アプリは2GB)が限界となります。
Excelの他にもChromeやらその他のソフトでメモリが使われています。
メモリを超えるサイズの文字列は作れません。
つまり残っているメモリ次第という事になります。


2バイト1文字なので、残りが1GBなら5億文字程度が限界になります。
Excel以外に色々なアプリが沢山動いていればもっと少なく、3億文字くらいでもエラーになります。
PC環境、実行のたびにも違った限界値になります。
32bitの場合は、2億文字くらいが限界と考えておいた方が良いでしょう。


64bitでもメモリが少なければ、、、
Excelを64bitにするならメモリはちゃんと積みましょうね。
解説は以上です。
正解としては、
「まだまだ、とことんいける」
これ以外はある意味どれも正解で良いでしょう。
気分としては、とことん行きたかったですけどね(笑)




同じテーマ「エクセル雑感」の記事

日付の謎:IsDateとCDate
ツイッター投稿用に文字数と特定文字で区切る
マクロ記録での色のマイナス数値について
VBAのString型の最大文字数について
Variantの数値型と文字列型の比較
Variant仮引数にRange.Valueを配列で渡す方法
Variant仮引数のByRefとByValの挙動違い
100桁の正の整数値の足し算
「VBA Match関数の限界」についての誤解
VBAで数値を漢数字に変換する方法
囲碁で相手の石を囲んで取るアルゴリズム


新着記事NEW ・・・新着記事一覧を見る

将棋とプログラミングについて~そこには型がある~|エクセル雑感(11月22日)
VBA100本ノック 30本目:名札作成(段組み)|VBA練習問題(11月22日)
VBA100本ノック 29本目:画像の挿入|VBA練習問題(11月21日)
VBA100本ノック 28本目:シートをブックに分割|VBA練習問題(11月19日)
VBA100本ノック 27本目:ハイパーリンクのURL|VBA練習問題(11月18日)
VBA100本ノック 26本目:ファイル一覧作成|VBA練習問題(11月17日)
VBA100本ノック 25本目:マトリック表をDB形式に変換|VBA練習問題(11月15日)
VBA100本ノック 24本目:全角英数のみ半角|VBA練習問題(11月14日)
VBA100本ノック 23本目:シート構成の一致確認|VBA練習問題(11月13日)
VBA100本ノック 22本目:FizzBuzz発展問題|VBA練習問題(11月12日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ