[[20150127095047]] 『sheet1の情報を分割し各シートへコピーしたい』(ex) ページの最後に飛ぶ

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

 

『sheet1の情報を分割し各シートへコピーしたい』(ex)

はじめまして。
単純作業ですが、知識が無いので質問させて下さい。

現在、sheet1のA列に約3000行の文字列が張ってあるのですが、
ある条件を付けて、各シートにコピーしようとしています。
内容としましては、各ファイルの中身を縦に貼り付けているだけですが、
ひとつひとつやるのがとても大変です。

■条件
 ・ファイルの区切りは空行
 ・1ファイルの中身は、行にして20行程度ですが、ファイルによって異なります

■やりたいこと
 ・< で始まる文字列を、新しいシートのB列へコピー
 ・それ以下に続く文字列は、1行改行して、C列へコピー
 ・C列にコピーする行は、1つ目のブランクで区切り、ブランクより右の文字列はD列へコピー
 ・</Location> という文字列が来るまで繰り返し(ここまでで1シート)
 ・新規に作成するシート名はなんでもいい

もし、簡単に、地域ごとに別々のシートに分けられる方法があったら教えてください。

よろしくお願いします。

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


・縦だか横だかよくわからない。(縦に貼り付ける、と言いながら、B列C列と、横に分解している)
・ファイルの区切り、ってなに? 空行含めて1ファイルではないの?(空行で切っても元は同じファイル)
・「<」で始まる文字列はいいとして、終わりは?(たぶん、「>」なんだろう…)
・HTML形式等なら必ず「<」始まりと思うが、始まらない場合もあるの?
・地域ってなに?(おそらく、Locationが前後に付いた文字列なのだろうけど…)
・単純作業だからといって、マクロ作成が簡単に済むわけじゃないよ?(簡単だと思ってるなら、ご自分でどうぞ)

とりあえず、明確なinput、outputが判らないので、実例を挙げて説明してください。
(???) 2015/01/27(火) 10:24


回答ありがとうございます。

・縦だか横だかよくわからない。(縦に貼り付ける、と言いながら、B列C列と、横に分解している)

 →sheet1に張っている情報はA列(縦)のみです。
  それを、別シートに貼っていく際、A列〜D列に展開した表にしたいと考えております。

・ファイルの区切り、ってなに? 空行含めて1ファイルではないの?(空行で切っても元は同じファイル)

 →sheet1に貼っている内容は、130ファイル(.conf)の中身です。
  表現に語弊がありました。
  内容としましては、Linuxサーバのある特定のディレクトリに格納している*.confファイル130個をmoreで引っ張ってきて、
  excelのsheet1のA1 へ貼り付けた状態です。

・「<」で始まる文字列はいいとして、終わりは?(たぶん、「>」なんだろう…)

 →開始は<Function>などで始まるのですが、開始だけは数パターンあるので、
  < で開始と表現させていただきました。
  終わりに関しては全て同じ文字列になるので、あの表現になりました。
  >で問題ないと思います。

・HTML形式等なら必ず「<」始まりと思うが、始まらない場合もあるの?

 →HTML形式等では、開始は<で問題ないと思われます。

・地域ってなに?(おそらく、Locationが前後に付いた文字列なのだろうけど…)

 →地域は関係ないです。申し訳ありません。別スレからのコピペミスです。

・単純作業だからといって、マクロ作成が簡単に済むわけじゃないよ?(簡単だと思ってるなら、ご自分でどうぞ)

 →今後も踏まえ、数時間で処理出来ればと思い、書かせていただきました。
  簡単ではないと思いますが、コツなどを教えていただけると助かります。

とりあえず、明確なinput、outputが判らないので、実例を挙げて説明してください。

 →input ファイル名 : test.xls

             シート名 : sheet1
         内容 : sheet1のA1からA3000までに以下の様な内容が繰り返し記載されている状況。例としては2ファイル分。

記載例)

:::::::::
xxx1.conf
:::::::::

<Location /var/ccc/ddd>

   ErrorDocument 404 default
   SVNPath /var/ccc/ddd
   SVNListParentPath off
   AuthType Basic
   AuthName "XXXX"
   AuthBasicProvider ldap
   AuthzLDAPAuthoritative off
   AuthLDAPURL ldap://XXX.co.jp
   AuthLDAPRemoteUserAttribute displayName
   AuthLDAPGroupAttribute uniqueMember
   Require ldap-group cn=deg,ou=Group,ou=sub,dc=dev,

</Location>

:::::::
xxx2conf
:::::::

<Location /var/eee/fff>

   ErrorDocument 404 default
   SVNPath /var/eee/fff
   SVNListParentPath off
   AuthType Basic
   AuthName "XXXX"
   AuthBasicProvider ldap
   AuthzLDAPAuthoritative off
   AuthLDAPURL ldap://XXX.co.jp
   AuthLDAPRemoteUserAttribute displayName
   AuthLDAPGroupAttribute uniqueMember
   Require ldap-group cn=deg,ou=Group,ou=sub,dc=dev,

</Location>




    output ファイル名 : test.xls 
             シート名 : sheet1、sheet2、sheet3 … sheet131
         内容 : 上記、inputのsheet1のA列に記載されている文字列を、confファイル別にsheet2〜sheet131にコピーしたい。

宜しくお願いします。
(ex) 2015/01/27(火) 12:57


説明と実例がかなり違いますね。やはり誤解の無いようにするには実例ですよ。
ただ、以下がまだよく判りません。

・実例中に「<」で始まるものがない。<Function>等があるのですよね?
「< Location /var/eee/fff>」のように、「<」の後ろに空白があったりしませんか?

・outputの例がない。BCD列の使い分けは?
 列を変えているのに、改行とか記述されていますが、これはセルに改行コードをいれるのか、行を変えるのか…。
 また、「<」で始まるものがない場合の処理は? 実例だとこれに当たりますよね?
 それとも「< Location /var/eee/fff>」はファイル区切りだけでなく、B列にも転記?
(???) 2015/01/27(火) 14:47


とりあえず、不明点は適当に解釈してVBA化した例。

 Sub test()
    Dim i As Long
    Dim iR As Long
    Dim cw As String
    Dim cName As String

    For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
        If Left(Cells(i, "A").Value, 1) = ":" Then
            cName = Cells(i + 1, "A").Value
            i = i + 3
        End If

        cw = Left(Cells(i, "A").Value, 4)
        If cw = "< Lo" Then
            Sheets.Add after:=Sheets(Sheets.Count)
            Sheets(Sheets.Count).Name = cName
        ElseIf cw = "</Lo" Then
        ElseIf Left(cw, 1) = "<" Then
            With Sheets(cName)
                iR = .Cells(.Rows.Count, "C").End(xlUp).Row + 1
                .Cells(iR, "B").Value = Cells(i, "A").Value
                .Cells(iR, "C").Value = " "
            End With
        ElseIf cw <> "" Then
            With Sheets(cName)
                iR = .Cells(.Rows.Count, "C").End(xlUp).Row + 1
                .Cells(iR, "C").Value = Split(Trim(Cells(i, "A").Value), " ")(0)
                .Cells(iR, "D").Value = Mid(Trim(Cells(i, "A").Value), Len(.Cells(iR, "C").Value) + 2)
            End With
        End If
    Next i
 End Sub
(???) 2015/01/27(火) 15:16

ご回答ありがとうございます。

・実例中に「<」で始まるものがない。<Function>等があるのですよね?
「< Location /var/eee/fff>」のように、「<」の後ろに空白があったりしませんか?

 →確認しましたが、全て <Location /var/eee/fff> のようになっております。
  < と L の間に、空白はありません。

・outputの例がない。BCD列の使い分けは?
 列を変えているのに、改行とか記述されていますが、これはセルに改行コードをいれるのか、行を変えるのか…。
 また、「<」で始まるものがない場合の処理は? 実例だとこれに当たりますよね?
 それとも「< Location /var/eee/fff>」はファイル区切りだけでなく、B列にも転記?

 →イメージが伝わっておらず、申し訳ありません。
  以下、outputイメージです。

    |     A列   |    B列    |   C列    |   D列     |
    ------------------------------------------------------------
  |     空白  |    条件   |  パラメタ  |   設定値   |
  ------------------------------------------------------------
    |       -     |<Location xxx> |              |             |
  ------------------------------------------------------------
    |             |               |AuthType      |Basic        |
  ------------------------------------------------------------
    |             |               |AuthName      |"XXXX"       |
  ------------------------------------------------------------
    |             |</Location>    |              |             |
  ------------------------------------------------------------

宜しくお願い致します。
(ex) 2015/01/27(火) 17:32


「<」の後に空欄ができたのは、ここの掲示板の自動整形のせいだった、ということですかね。

 Sub test()
    Dim i As Long
    Dim iR As Long
    Dim cw As String
    Dim cName As String

    For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
        If Left(Cells(i, "A").Value, 1) = ":" Then
            cName = Cells(i + 1, "A").Value
            i = i + 3
        End If

        cw = Left(Cells(i, "A").Value, 4)
        If cw = "<Loc" Then
            Sheets.Add after:=Sheets(Sheets.Count)
            Sheets(Sheets.Count).Name = cName
            Sheets(Sheets.Count).Range("B1:D1") = Array("条件", "パラメタ", "設定値")
        End If

        If Left(cw, 1) = "<" Then
            With Sheets(cName)
                iR = .Cells(.Rows.Count, "C").End(xlUp).Row + 1
                .Cells(iR, "B").Value = Cells(i, "A").Value
                .Cells(iR, "C").Value = " "
            End With
        ElseIf cw <> "" Then
            With Sheets(cName)
                iR = .Cells(.Rows.Count, "C").End(xlUp).Row + 1
                .Cells(iR, "C").Value = Split(Trim(Cells(i, "A").Value), " ")(0)
                .Cells(iR, "D").Value = Mid(Trim(Cells(i, "A").Value), Len(.Cells(iR, "C").Value) + 2)
            End With
        End If
    Next i
 End Sub
(???) 2015/01/27(火) 18:12

度々ありがとうございます。

おそらく、空白は自動整形かと思われます。

いただいたコードを貼り付け、Excelで実施してみたのですが、
以下エラーメッセージが表示され、動きませんでした。

[エラーメッセージ]
実行時エラー '1004':
アプリケーション定義またはオブジェクト定義のエラーです。

因みにですが、各処理対し、コメントを入れていただくことは可能でしょうか。
素人ですので、殆どの処理内容を理解出来ておりません。

お手数お掛けしますが、宜しくお願い致します。
(ex) 2015/01/28(水) 08:40


連続ですいません。

再度確認してみましたが、マクロを実行しましたところ、
1シートは正常にイメージ通り作成され、2シート目を追加したところで
止まっているように見えました。

confファイル名がシート名になるように設定いただきましたが、
おそらく、confファイル名がExcel上で設定されている
シート名の上限を超過しているためのエラーかと思われます。

この場合、どこを修正すれば動きますでしょうか。

また、度重なる依頼となってしまい大変恐縮ですが、
sheet1のA列に貼っている今の情報を編集し、
以下通り加工した結果を、sheet2へ貼り付けることも可能なのでしょうか。

■完成イメージ
 input  : 前回と同様

 output : 以下、sheet2のイメージとなります。

 
  | A列   |    B列    |   C列    |   D列 |

    ------------------------------------------------------------
  xxx.conf
    ------------------------------------------------------------
  |     空白  |    条件   |  パラメタ  |   設定値   |
  ------------------------------------------------------------
    |       -     |<Location xxx> |              |             |
  ------------------------------------------------------------
    |             |               |AuthType      |Basic        |
  ------------------------------------------------------------
    |             |               |AuthName      |"XXXX"       |
  ------------------------------------------------------------
    |             |</Location>    |              |             |
  ------------------------------------------------------------
    fff.conf
    |     空白  |    条件   |  パラメタ  |   設定値   |
  ------------------------------------------------------------
    |       -     |<Location xxx> |              |             |
  ------------------------------------------------------------
    |             |               |AuthType      |Basic        |
  ------------------------------------------------------------
    |             |               |AuthName      |"XXXX"       |
  ------------------------------------------------------------
    |             |</Location>    |              |             |
  ------------------------------------------------------------
    yyy.conf
    |     空白  |    条件   |  パラメタ  |   設定値   |
  ------------------------------------------------------------
    |       -     |<Location xxx> |              |             |
  ------------------------------------------------------------
    |             |               |AuthType      |Basic        |
  ------------------------------------------------------------
    |             |               |AuthName      |"XXXX"       |
  ------------------------------------------------------------
    |             |</Location>    |              |             |
  ------------------------------------------------------------
  ※ A〜D列が何故か少しずれてしまってます

宜しくお願いいたします。

(ex) 2015/01/28(水) 08:56


実行時エラー '1004':
アプリケーション定義またはオブジェクト定義のエラーです。

 エラーで止まってた時に黄色く光っているコードはどこでしたか?

(β) 2015/01/28(水) 09:28


追加するシートが既に存在している場合、シート名変更時にエラーになります。たぶんそこかと。
データ中に同じconfファイル名が登場するか、シート名としては認められていない文字が含まれているのでしょう。

変更案の方ならば、出力シートは1つ固定なので、問題ないでしょう。

 Sub test()
    Dim i As Long
    Dim iR As Long
    Dim cw As String
    Dim cName As String

    With Sheets("Sheet2")
        For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
            If Left(Cells(i, "A").Value, 1) = ":" Then
                cName = Cells(i + 1, "A").Value
                i = i + 3
            End If

            cw = Left(Cells(i, "A").Value, 4)
            If cw = "<Loc" Then
                iR = iR + 1
                .Cells(iR, "A").Value = cName
                iR = iR + 1
                .Range(.Cells(iR, "B"), .Cells(iR, "D")) = Array("条件", "パラメタ", "設定値")
            End If

            If Left(cw, 1) = "<" Then
                iR = iR + 1
                .Cells(iR, "B").Value = Cells(i, "A").Value
                .Cells(iR, "C").Value = " "
            ElseIf cw <> "" Then
                iR = iR + 1
                .Cells(iR, "C").Value = Split(Trim(Cells(i, "A").Value), " ")(0)
                .Cells(iR, "D").Value = Mid(Trim(Cells(i, "A").Value), Len(.Cells(iR, "C").Value) + 2)
            End If
        Next i
    End With
 End Sub

なお、コメントは、自分の仕事で作成したものにはきっちり入れますが、ここでサンプル作成したものには入れません。
そこはコーディングを読んで理解した上で、貴方が書き入れてください。
(ステップ実行すれば判るくらいの命令しか使用していませんよ)

「初心者だから判らない」?違います。 「自分で調べないから判らない」だけです。
初心者ならば、慣れている人より、調べたり書いたりするのは、時間がかかって当たり前ですよ。
(???) 2015/01/28(水) 09:34


(β)さん

Sheets(Sheets.Count).Name = cName

処理で止まってました。
(ex) 2015/01/28(水) 09:38


(???)さん

度々ありがとうございます。

エラーの件、承知しました。
重複等ないか、確認してみます。

変更案のソースにつきましては、実施してみましたところ、
想定通り、結果が出力されていました。
本当にありがとうございます。

また、コメントに関してですが、仰るとおり、自分の理解する姿勢が足りないと思います。
サンプルコードで使われている処理内容を調べ、
自分なりに習得していきたいと思います。

ありがとうございました。
(ex) 2015/01/28(水) 09:44


小技的なところだけ解説しておきます。

(1)パラメタ

 .Cells(iR, "C").Value = Split(Trim(Cells(i, "A").Value), " ")(0)

Trim関数で前後の空白を除去していますが、これは不要だと思います。念のための処理です。
Split関数は、指定したトークンで区切って、配列を返します。普通はこれをVariant型の変数に代入しますが、
区切ったものの先頭しか使用しないので、直接(0)番目の値だけ得ています。

(2)設定値

 .Cells(iR, "D").Value = Mid(Trim(Cells(i, "A").Value), Len(.Cells(iR, "C").Value) + 2)

これは、データの先頭(パラメタ)を除いた、残り全部を得ています。Mid関数は(文字列,先頭,長さ)を指定しますが、
「長さ」を省略すると、後ろ全部採用される事を利用しています。
(???) 2015/01/28(水) 10:24


(???)さん

素晴らしい解説、ありがとうございます。
とても分かり易いです。

直感的に感じたのは、私の関数の知識の無さですね。
関数を熟知していれば、その特性を活かした使い方や、
応用的な技など、バリエーションが増えるんですね。

サンプルソースを提供いただいた上、
ここまでして下さり、本当に感謝しております。

ありがとうございました。
(ex) 2015/01/28(水) 12:55


コメント返信:

[ 一覧(最新更新順) ]


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