エクセル雑感
ツイッター投稿用に文字数と特定文字で区切る

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

ツイッター投稿用に文字数と特定文字で区切る


ツイッターで出したVBAのお題です。
ツイッター投稿には文字数制限がありますので、セルに入れた下書き文章をツイート用に区切る問題です。


お題のツイート

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

【エクセルお題】
ツイートの下書きをA1セルに入れています。
バイト数はLENB関数で分かりますが、単純に280バイトで区切ってしまうと文章が尻切れになってしまいます。
そこで280バイトを超えない範囲で区切りのよいところで分割したい。
→画像に続く

VBA マクロ 文字数と特定文字で区切る

【エクセルお題】
ツイートの下書きをA1セルに入れています。
バイト数はLENB関数で分かりますが、単純に280バイトで区切ってしまうと文章が尻切れになってしまいます。
そこで280バイトを超えない範囲で区切りのよいところで分割したい。
280バイト以内の最後の。または改行で複数に分割してください。
※関数でもVBAでもどちらでも構いません。
※関数は2分割でもOKとします。
ちなみに答えはまだ用意していません。
関数は分割数が不定の場合はできるか不明、VBAは後で書く予定。
【エクセルお題】
ツイートの下書きをA1セルに入れています。
バイト数はLENB関数で分かりますが、単純に280バイトで区切ってしまうと文章が尻切れになってしまいます。
そこで280バイトを超えない範囲で区切りのよいところで分割したい。
280バイト以内の最後の。
または改行で複数に分割してください。
※関数でもVBAでもどちらでも構いません。
※関数は2分割でもOKとします。
ちなみに答えはまだ用意していません。
関数は分割数が不定の場合はできるか不明、VBAは後で書く予定。

ツイッターで頂いた回答

VBA マクロ 文字数と特定文字で区切る


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

サイト管理人のVBAでの回答サンプル



Option Explicit

Sub sample()
  Dim ary
  Dim i As Long
  ary = TweetArray(Range("A1").Value, 280, vbLf, "。")
  For i = LBound(ary) To UBound(ary)
    Range("A2").Offset(i - LBound(ary)) = ary(i)
  Next
End Sub

'ツイッター投稿用文章区切り
Function TweetArray(ByVal str As String, _
          ByVal num As Long, _
          dlmt1 As String, _
          dlmt2 As String) As String()
  Dim ary1() As String, ary2() As String, ary3() As String
  Dim i As Long, j As Long, k As Long
  
  '2つの区切り文字で区切った配列作成
  ary1 = Split(str, dlmt1)
  For i = LBound(ary1) To UBound(ary1)
    ary2 = Split(ary1(i), dlmt2)
    For j = LBound(ary2) To UBound(ary2)
      ReDim Preserve ary3(k)
      ary3(k) = ary2(j)
      'Splitした区切り文字を追加しておく
      If i <> UBound(ary1) Or j <> UBound(ary2) Then
        ary3(k) = ary2(j) & IIf(j = UBound(ary2), dlmt1, dlmt2)
      End If
      k = k + 1
    Next
  Next
  
  '配列から指定文字数以内で連結しつつ別配列作成
  Dim strLeft As String, strRight As String
  Dim aryRtn() As String
  ReDim aryRtn(0)
  Dim ix As Long
  For i = LBound(ary3) To UBound(ary3)
    Do
      'バイトでLeft関数:残りをByRef引数で受け取り
      strLeft = JisLeft(ary3(i), num, strRight)
      '出力配列に文字追加して文字数超えるか確認
      If JisLen(aryRtn(ix) & strLeft) >= num Then
        ix = ix + 1
        ReDim Preserve aryRtn(ix)
        aryRtn(ix) = strLeft
      Else
        aryRtn(ix) = aryRtn(ix) & strLeft
      End If
      '残りを元の配列に戻す
      ary3(i) = strRight
      
    Loop Until strRight = "" '残りがなくなるまで
  Next

  TweetArray = aryRtn
End Function

'shift-jisバイトでのLeft関数:残りをByRef引数で戻している
Function JisLeft(ByVal str As String, _
         ByVal num As Long, _
         ByRef strRight As String) As String
  Dim i As Long, j As Long
  For i = 1 To Len(str)
    If JisLen(Left(str, i)) > num Then
      Exit For
    End If
  Next
  JisLeft = Left(str, i - 1)
  strRight = Mid(str, i)
End Function

'shift-jisバイトでのLen関数
Function JisLen(ByVal str As String) As Long
  JisLen = LenB(StrConv(str, vbFromUnicode))
End Function

VBAでの回答サンプルの解説

Function JisLeft
でのLeftで取り出した残りの文字列をByRefで返している点に注意してください。
今回の場合に、この方法が良いかは何とも言えない実装になっていますが、ByRef引数の使い方の参考にして貰えればと思います。

分かりづらいのは、配列の使い方だと思いますので、以下に配列の変遷を記載しておきます。

ary1の内容
VBA マクロ 文字数と特定文字で区切る

受け取った文字列ををvbLfで区切って配列にします。
文字区切りには、Split関数を使っています。
各要素(区切り文字)ごとに区切られた文字列から1次元配列を作成し返します。つまり、Split関数は、文字列を指定の区切り文字で分割し1次元配列を作る関数です。マクロVBAの文字列操作においてはSplit関数はとても重要かつ必須になりますので、しっかりと習得してください。

ary2の内容
VBA マクロ 文字数と特定文字で区切る

ary1の内容を"。"で区切って配列にします。
最後の""は、"。"で区切ったことにより、最後の"。"の後が空文字の配列で作成されています。
この最後の要素は不要ですが、そのままでも後処理に問題ないのでそのままにしています。

ary3の内容
VBA マクロ 文字数と特定文字で区切る

ary2を全て一つにした配列になります。

ary3から一つずつ取り出しながら、280バイト以内で連結しaryRtnを作成しています。
aryRtnが完成した配列になります。



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

保護されたブックの非表示シートについて
文字列のセルだけ結合
時間に関する関数の扱い方
COUNTIF関数の結果は?
【超難問】エクセル数式問題
IFステートメントの判定
日付の謎:IsDateとCDate
ツイッター投稿用に文字数と特定文字で区切る
マクロ記録での色のマイナス数値について
VBAのString型の最大文字数について
Variantの数値型と文字列型の比較


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

Variantの数値型と文字列型の比較|エクセル雑感(7月1日)
VBAのVariant型について|VBA技術解説(6月30日)
VBAのString型の最大文字数について|エクセル雑感(6月20日)
VBAで表やグラフをPowerPointへ貼り付ける|VBAサンプル集(6月19日)
アクティブシート以外の表示(Window)に関する設定|VBA技術解説(6月17日)
マクロ記録での色のマイナス数値について|エクセル雑感(6月16日)
ツイッター投稿用に文字数と特定文字で区切る|エクセル雑感(6月15日)
日付の謎:IsDateとCDate|エクセル雑感(6月14日)
IFステートメントの判定|エクセル雑感(6月13日)
インクリメンタルサーチの実装|ユーザーフォーム入門(6月12日)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.マクロって何?VBAって何?|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|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」をお願いいたします。
本文下部へ