[[20150320233358]] 『セル内の文字を,指定文字数で複数行に貼り付け』(wankon) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『セル内の文字を,指定文字数で複数行に貼り付け』(wankon)

どうしていいか分からず,ここで質問させていただきます。

A1セルに,セル内改行付きの文章が入っています。
それを,指定文字数で区切り,B1から下に順に値を貼り付けしたいのです。
ただし,条件があり,
 文の始めに「,」「。」がこないように禁則処理する。(その場合は,上のセルに一文字追加。)
 また,セル内での改行「Alt+Enter」があるときは,そこから先は文字数が満たなくても次のセルに移動する。

過去の書き込みを見て,次のようなものを作ったのですが,たまに同じフレーズがあると,
無限ループしてしまいます。

「マクロ」
v = Split(Text, Chr(10))
For i = 0 To UBound(v)

   ss = v(i)
      Do
   p = IIf(Left(ss, 1) = "・", 34, 32)
                '先頭行が「・」なら全角17文字,それ以外は全角16文字で折り返す
      s = StrConv(LeftB(StrConv(ss, vbFromUnicode), p), vbUnicode)
      b = LenB(StrConv(s, vbFromUnicode))
      If b > p Then s = Left(s, Len(s) - 1)
      ss = Replace(ss, s, "")
      Set MyRange = Sheets("設定").Range("A3:AR3").Find(what:=Left(ss, 1), lookat:=xlPart)      '禁則処理文字一覧はRange("A3:AR3")に入力してある
      If Not MyRange Is Nothing Then
           s = s & Left(ss, 1)
          ss = Mid(ss, 2)
      Else
          s = s
      End If

      Sheets("sheet2").Cells(1, 2).Offset(n + 1).Value = s
        n = n + 1
      Loop While Len(ss) > 0
    Next
「マクロ終了」

さらに,値を貼り付けする前に,何行貼り付けるか数えることはできますか?
よろしくお願いします。

< 使用 Excel:Excel2010、使用 OS:unknown >


 おもしろそうなテーマですが、眠いので、コードがすらっと頭に入りません。
 ですので、「森を見ずに、木のみを見て」原因が本当に、文章中に同じフレーズがあって、Replace で一挙に削除され
 文字列が短くなりすぎということであるなら最初(もっというなら、先頭でしょうけど)の該当文字列だけを
 削除すればいいのではないですか?
 方法はいくつかあると思いますが、ややこしいのは、眠気で朦朧としていますのでシンプルなものだけでいきますと
 以下、参考になりますか?

 勘違いしてたらスルーしてください。

 Sub Test()
    Dim s As String
    Dim ss As String
    Dim reg As Object

    Set reg = CreateObject("VBScript.RegExp")

    s = "あいうえお"
    ss = "あいうえおかきくけこあいうえおかきくけこ"

 'VBA Replace関数(無条件)
    MsgBox Replace(ss, s, "")

 'VBA Replace関数(最初のみ)
    MsgBox Replace(ss, s, "", Count:=1)

 '正規表現 Replaceメソッド
    reg.Pattern = s
    MsgBox reg.Replace(ss, "")

 '文字列の先頭ということでよければ

 'VBA MID関数
    MsgBox Mid(ss, Len(s) + 1)

 End Sub

 で、「値を貼り付けする前に,何行貼り付けるか数えることはできますか? 」

 これも、いろんなやり方があると思いますが、直接転記せず、Redim Preserve を使いながら
 1次元配列に格納し、最後にその要素数を取得、転記は Worksheetfunction.Transpose を使う。
 あるいは、キーをユニークにしたDictionaryのItemに格納し、最後に要素数を把握し、転記は
 DictionaryのItems を、同様に WorksheetFunction.Transposeで。

(β) 2015/03/21(土) 02:30


設定シートの A3 に 全角の 。 をいれ、
ss = Replace(ss, s, "", Count:=1) に変更し
Text に以下の文字列を入れ、あとはそちらのこーどのまま動かしました。

    Text = "。あいうえおかきくけこさしすせそた。あいうえおかきくけこさしすせそた" & vbLf & _
           "。1234567890123456。1234567890123456" & vbLf & _
           "。ABCDEFGHIJKLMNOP。ABCDEFGHIJKLMNOP"

Sheet2の結果は以下です。
先頭に 。 が入っているのですが、よろしいのですか?

。あいうえおかきくけこさしすせそ
た。あいうえおかきくけこさしすせ
そた
0.123456789
6.123456789
56
。ABCDEFGHIJKLMNO
P。ABCDEFGHIJKLMN
OP

以下の検索値と検索領域の関係、これでいいのですか?

Set MyRange = Sheets("設定").Range("A3:AR3").Find(what:=Left(ss, 1), lookat:=xlPart)

ちなみに、上記文字列での実行の最初、ss は

た。あいうえおかきくけこさしすせそた

その Left(ss,1) ですから What: は た になりますが?
(β) 2015/03/21(土) 07:34


>以下の検索値と検索領域の関係、これでいいのですか?

>Set MyRange = Sheets("設定").Range("A3:AR3").Find(what:=Left(ss, 1), lookat:=xlPart)

そうですね,貼り付ける領域とかぶってしまいますね。
Set MyRange = Sheets("設定").Range("A3:A10").Find(what:=Left(ss, 1), lookat:=xlPart)
のように,A列に縦に入力するように変更しました。

>先頭に 。 が入っているのですが、よろしいのですか?
文章の先頭に「。」が入ることはないので,考えてませんでした。
途中にしか入りません。スルーして構いません。

また,ループする条件が今一自分も分かっていません。単純に同じフレーズを入れても,ループしないことの方が多い気がします。
(wankon) 2015/03/21(土) 07:46


 >そうですね,貼り付ける領域とかぶってしまいますね。 

 いえ、貼り付ける領域は Sheet2 ですよね。検索領域は 設定 シートですから、かぶらないですよ?

 気になったのは、A3〜AR3 まで、44個も禁則文字があるんだなぁということ、それはいいんですが
 セルに1文字ずついれているんだと思います。そうすると、1文字で1文字ずつの領域の Find ですから
 xlPart でもいいですけど、理屈からいえば xlWhole だなと。
 で、たとえばセルに1文字ずつではなく、たとえば A3 に禁則文字を続けて1文字列として入力しておけば
 わざわざFind という重いものをつかわなくても InStr とか ワイルドカードの Like 比較で十分なのでは?
 そういったあたりです。

 要件がよくわからないのですが、先頭が ・ かという判定は、文字列全体の先頭ということですか?
 それとも、分割した、それぞれの文字列の先頭ということですか?

 それと、分割したものが

 あああああああ 
 。いいいいいい

 桁数は別にして、こうなったとしたら、 あああああああ は、規定通りの桁数ですが、
 それを、あああああああ。 と、。を移動させることで、規定桁を超えますが、それは、それでいいのですね?

 いずれにしても、お手伝いできるところがあれば、お手伝いしたいとは思います。

 上のほうでコメントした、転記前に行数を把握する件、サンプルです。新規ブックでお試しください。

 Sub Test2()
    Dim w As Variant
    Dim s As Variant

    Columns("A").Clear

    For Each s In Array("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj")

        If Not IsArray(w) Then
            ReDim w(1 To 1)
        Else
            ReDim Preserve w(1 To UBound(w) + 1)
        End If

        w(UBound(w)) = s

    Next

    MsgBox UBound(w) & " 件でした"

    Range("A1").Resize(UBound(w)).Value = WorksheetFunction.Transpose(w)

 End Sub

 Sub Test3()
    Dim dic As Object
    Dim s As Variant

    Columns("A").Clear
    Set dic = CreateObject("Scripting.Dictionary")

    For Each s In Array("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj")

        dic(dic.Count) = s

    Next

    MsgBox dic.Count & " 件でした"

    Range("A1").Resize(dic.Count).Value = WorksheetFunction.Transpose(dic.items)

 End Sub

(β) 2015/03/21(土) 09:27


βさんのアドバイスを元に下記スレのコードを修正してみました。
  
[[20140324144850]] 
  
 Sub test4()
    Dim myText As String
    Dim v
    Dim i As Long
    Dim p As Long
    Dim ss As String, s As String
    Dim b As Long
    Dim n As Long
    Dim w() As String

    Columns("B").ClearContents
'    myText = Cells(1, "A").Text
    myText = "。あいうえおかきくけこさしすせそた。あいうえおかきくけこさしすせそた" & vbLf & _
           "。1234567890123456。1234567890123456" & vbLf & _
           "。ABCDEFGHIJKLMNOP。ABCDEFGHIJKLMNOP"

    v = Split(myText, Chr(10))
    For i = 0 To UBound(v)
        ss = v(i)
        Do
            p = IIf(Left(ss, 1) = "・", 34, 32)
            s = StrConv(LeftB(StrConv(ss, vbFromUnicode), p), vbUnicode)
            b = LenB(StrConv(s, vbFromUnicode))
            If b > p Then s = Left(s, Len(s) - 1)
            ss = Replace(ss, s, "", Count:=1)
            If Left(ss, 1) Like Sheets("設定").Range("A3").Value Then
'            Select Case Left(ss, 1)
'                Case ",", ",", "、", ".", "。"
                    s = s & Left(ss, 1)
                    ss = Mid(ss, 2)
'            End Select
            End If
'            Cells(1, "B").Offset(n).Value = s
            n = n + 1
            ReDim Preserve w(1 To n)
            w(n) = s
         Loop While Len(ss) > 0
    Next
    MsgBox n & "行貼り付け"
    Cells(1, "B").Resize(n).Value = WorksheetFunction.Transpose(w)

 End Sub

(マナ) 2015/03/21(土) 10:49


皆様,ご教授ありがとうございます。
少し勘違いから変なコメントをしてすいません。

禁則処理文字ですが,そんなに沢山無いとは思うのですが,国語の作文で文頭に来てはいけないもの,
,。」』]ゃゅょ(小さい文字)
くらいの設定で,後から付け足すことも考えて,個別にセルに入力してました。

始めに文章例を書けば良かったですね。
1つのセルに次のような文章が入っているとき,

・春はあけぼの。やうやう白くなりゆく山ぎは,少し明りて紫だちたる雲の細くたなびきたる。
・夏は夜。月の頃は更なり。闇もなほ。螢の多く飛び違ひたる。
 また、ただ一つ二つなど、ほのかにうち光りて行くもをかし。雨など降るもをかし。

・春はあけぼの。やうやう白くなりゆ
く山ぎは,少し明りて紫だちたる雲
の細くたなびきたる。
・夏は夜。月の頃は更なり。闇もなほ。
螢の多く飛び違ひたる。
 また、ただ一つ二つなど、ほのか
にうち光りて行くもをかし。雨など
降るもをかし。

と結果を出力したいのです。
βさんので,出来ていると思うのですが,禁則文字が1つずつセルに入っている状況で,
禁則処理の簡単な書き方があれば…と思います。

また,なかなか再現が難しいのですが,無限ループに入ってしまう原因が分かりません。
よろしければ,お願いします。

(追記)
・春はあけぼの。やうやう白くなりゆく山ぎは,少し明りて紫だちたる雲の細くたなびきたる。春はあけぼの。やうやう白くなりゆく山ぎは,少し明りて紫だちたる雲の細くたなびきたる。
・春はあけぼの。やうやう白くなりゆく山ぎは,少し明りて紫だちたる雲の細くたなびきたる。

と1つのセルに入力したところ,無限ループではありませんが,途中が省略されて結果が出ました。
原因が分かりません。
(wankon) 2015/03/21(土) 15:59


 この2行が改行コードで連結されて1セルに入っているということですね。

 (マナ) 2015/03/21(土) 10:49 のマナさんのコードの myText へのセットを以下にして実行しますと

 ・春はあけぼの。やうやう白くなりゆ
 く山ぎは,少し明りて紫だちたる雲
 の細くたなびきたる。春はあけぼの。
 やうやう白くなりゆく山ぎは,少し
 明りて紫だちたる雲の細くたなびき
 たる。
 ・春はあけぼの。やうやう白くなりゆ
 く山ぎは,少し明りて紫だちたる雲
 の細くたなびきたる。

 このように、見事に分割されますよ。

    myText = "・春はあけぼの。やうやう白くなりゆく山ぎは,少し明りて紫だちたる雲の細くたなびきたる。春はあけぼの。やうやう白くなりゆく山ぎは,少し明りて紫だちたる雲の細くたなびきたる。" & vbLf & _
"・春はあけぼの。やうやう白くなりゆく山ぎは,少し明りて紫だちたる雲の細くたなびきたる。"

(β) 2015/03/21(土) 16:56


 >禁則文字が1つずつセルに入っている状況で, 禁則処理の簡単な書き方があれば…と思います。

 たとえば 設定 シートの A3から右に1つずつ、任意の数の禁則文字が書かれていたとします。
 以下のテストでは、全角の 。 と 、 と ゃ(ちいさい ゃ) を入れてあります。

 コードの最初に禁則文字群を NGchars にいれます。

 で、実行時には ワイルドカードで、調べたい文字を Like比較します。
 結果が True なら 禁則文字、 False なら OK文字になります。

 Sub Test5()
    Dim NGchars As String
    Dim s As String

    With Sheets("設定")
        NGchars = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(.Range("A3", .Cells(3, Columns.Count).End(xlToLeft)))))
    End With

    s = "。"
    MsgBox NGchars Like "*" & s & "*"

    s = "ゃ"
    MsgBox NGchars Like "*" & s & "*"

    s = "A"
    MsgBox NGchars Like "*" & s & "*"

    s = "や"
    MsgBox NGchars Like "*" & s & "*"

 End Sub

(β) 2015/03/21(土) 17:09


 >また,なかなか再現が難しいのですが,無限ループに入ってしまう原因が分かりません

 コピペの仕方を変えてみて、やっとこちらでも再現できました。
 目に見えないゴミがはいっていると思われます。

 Sub ゴミ取り()
    ActiveCell.Value = Replace(ActiveCell.Value, ChrW(160), "")
 End Sub

 を実行するとOKならば、原因確定です。
 その場合、コードは

 ss = Replace(ss, s, "", Count:=1)
 を、↓に変更(βさんご提案のもう一つの方法)
 ss = Mid(ss, Len(s) + 1)

 にするとよいでしょう。

(マナ) 2015/03/21(土) 19:53


ごめんなさい。試さずに回答していました。

 >ss = Mid(ss, Len(s) + 1)

 これだと、ゴミは残ったままなので、別法です。

 ss = v(i)
 の次に、↓を1行追加
 ss = Replace(ss, ChrW(160), "")

(マナ) 2015/03/21(土) 22:23


うわー,マナさん!すごい!ありがとうございます!
そんなことが原因だったとは…
いろんな人が作る文章に対して,この作業を行うので,
何かしらの原因があるとは思っていたのですが…

みなさん,ありがとうございました!
何とか解決出来そうなので,あと少し頑張ります!
(wankon) 2015/03/22(日) 03:19


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.