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

以前同じ質問をさせて頂いたのですが、説明不足であったため再投稿いたします。

【エクセル VBA】
VBAを使って複数のCSVを結合させたいのですが、コンマ区切りの値がデータ上に存在するため上手くまとまりません。

バッチ等でまとめる方法ではなく、どうしてもVBAでやらなければならないので、その方法をご教授下さい。

また、結合するCSVはエクセルを開いた時に選択できるようにしたいです。
(特定のファイル上を対象等では無く。)



現在使用しているVBAは以下のものになります。
-----------------------------------------------------

Sub CsvIn()
'CSVファイルの読み込み
Dim CsvFileName As Variant
Dim Li As String
Dim Bf() As String
Dim R As Long
Dim ShMain As Worksheet
Dim FlNo As Integer
Dim FFlNo As Integer

With ThisWorkbook 'シート&パスの設定
Set ShMain = .Worksheets("Sheet1")
ChDrive .Path
ChDir .Path
End With
'複数のファイルの選択を可に設定
CsvFileName = Application.GetOpenFilename _
(filefilter:="CSVファイル(*.csv),*.csv", _
Title:="CSVファイル選択", MultiSelect:=True)
If VarType(CsvFileName) = vbBoolean Then Exit Sub 'キャンセル時の処置
R = 1 '行の初期値
For FlNo = 1 To UBound(CsvFileName) 'ファイル数分ループ
FFlNo = FreeFile '---使用可能なファイル番号取得
Open CsvFileName(FlNo) For Input As #FFlNo
Do Until EOF(FFlNo) '最終行までループ
Line Input #FFlNo, Li '一行読み込み
Bf = Split(Li, ",") 'カンマで分割し配列に代入
If UBound(Bf) >= 0 Then '空白行の処理を飛ばす
With ShMain '1行分のデータをセルに出力
.Range(.Cells(R, 1), Cells(R, UBound(Bf) + 1)).Value = Bf
End With
End If
R = R + 1
Loop
Close #FFlNo
Next FlNo
End Sub

-----------------------------------------------

参考になりそうなサイト
http://excel-ubara.com/excelvba5/EXCELVBA257.html



よろしくお願いします。

質問者からの補足コメント

  • 問題点:
    文字列にコンマが入っている場合がある(ここではあるセル上のバージョン情報が12,3,0,0のように表示されている)ため、CSVをエクセルに取り込んだ際に12、3、0、0と区切られてしまいます。
    これをVBAで文字列内のコンマを削除するという処理を追加できればと思っています。


    例を挙げると以下のサイトに似たことが書いてあります。
    http://pasonal.com/vba-partition/

      補足日時:2017/08/28 14:55
  • Copyコマンドを使用し、ただ単にCSVファイルを結合しておりました。

    CSVを結合した後に、決まった作業があるのですが、なるべく一つのファイル(Excel)で全ての作業を完結させたいと考えておりますので、どうしてもVBAでCSVの結合も行いたいと考えております。

    No.2の回答に寄せられた補足コメントです。 補足日時:2017/08/28 15:25
  • 私の説明不足&知識不足で困惑させてしまい申し訳ありません。


    イメージしている順序は

    1、VBAを含むエクセルを起動(現在作成しようとしているもの)
    2、結合したいCSVファイルを選択
    3、エクセルにCSVデータが取り込まれる
    4、普段行っている決まった作業を行う(ここもVBAでするつもりですが、ここに関しては何とかなりそうです)
    5、VBAで行えない作業を手動で行う
    6、保存

    になります。


    そのため、ファイル名は保存する際に自由に決められるようにします。

    よろしくお願いします。

    No.3の回答に寄せられた補足コメントです。 補足日時:2017/08/28 16:42
  • 列によって場合分けをする感じではなく、
    基本的にデータ内(セル内)にコンマがある場合はすべて無視したいです。
    (エクセル側がコンマをセルの区切り目と捉えてしまうため)

    例えは、捕捉で張らせていただいたリンク先にあります。


    説明が下手で申し訳ありません。

    No.4の回答に寄せられた補足コメントです。 補足日時:2017/08/28 17:47
  • うれしい

    ①で間違いありません。

    ---------------------
    ①「"」で囲まれた中にある物は文字列として扱い、その中にある「,」は区切り記号としてはつかわないが、それ以外の「,」は区切り記号として扱う。
    例 1-1:「123,45,"678,90"」→「123」「45」「"67890"」
    例 1-2:「123,45,"678,90"」→「123」「45」「67890」
    ----------------------

    わかりやすい質問ありがとうございます

    No.5の回答に寄せられた補足コメントです。 補足日時:2017/08/28 18:19
  • GooUserラックさん、Windfallerさん

    ご回答有り難うございました。大変感謝しております。
    特にラックさんは分かりやすい質問を何度も投げ掛けてくださり、助かりました。


    明日試し、結果を報告させていただきます。

      補足日時:2017/08/28 20:43
  • コンマ区切りの値も問題なく取り込むことができました。
    しかし、ファイルを結合した際に、一部のデータが消えてしまっているみたいです。
    大変申し訳なくは思うのですが、原因が私にはわからない状態です。

    ファイルを見せることができれば早いのですが、一部機密情報がふくまれているため、元データを変換して一部を張り付けさせて頂きます。 何か分かられれば幸いです。


    "マシン名","2017/08/02","~情報","K22","4/3/2014"
    "マシン名1","2017/08/02","~情報","SN Tr","Stop","C:\wi\Syst\snp.exe","ユーザ名"
    "マシン名2","2017/08/02","~情報","ehmsas.exe","C:\Wi\win\-win5.exe","Ms Cor","6,1,30,1","Ms Sys","2009/07/14"

    No.8の回答に寄せられた補足コメントです。 補足日時:2017/08/29 09:56
  • つらい・・・

    複数のファイルを読み込んだ際に、一部データが消えてしまっている(または取り込めていない)状態です。

    データの一部は、何かデータが取り込めていない理由に関連しているかと思い張り付けさせて頂きました。

    ご迷惑をおかけします..
    もし難しそうでしたら、元ファイルのカンマを置換する→取り込む
    手順も考えております。

    No.11の回答に寄せられた補足コメントです。 補足日時:2017/08/29 10:55
  • へこむわー

    返答が遅くなり申し訳ありませんでした。

    複数選択の方法は分かりますが、複数ファイルを取り込んだ際に、一部のデータが消えてしまっている(または取り込めていない)状態です。
    同じ列に似た値があると上書かれてしまうということはありませんでしょうか?

    また消えている部位の元データを見てみたのですが、特段ルールが異なるようなことはございませんでした。

    補足ですが、データ量は結構多くまとめた際に2万行程になります。

    No.13の回答に寄せられた補足コメントです。 補足日時:2017/08/29 16:23

A 回答 (15件中1~10件)

No.13 に対する補足コメントについて



ですから!
そのダメな所のデータを数行抜き出したものでCSVファイルを作成して実験してみてください。
それでも症状が出るならばその数行のデータを提示してください。

大変申し訳ないのですが、こちらはそちらの状況が見えないので「特段ルールが異なるようなことはございませんでした。」は、あなたが気づかないだけの場合が多いのでそれを提示していただきたいのです。
「同じ列に似た値があると上書かれてしまうということはありませんでしょうか?」については1文字ずつ「"」「,」が有った時だけ特別な作業をしているだけなので考えにくいです。

もしかしての考えられそうなものとして
・文字コードのせいで1つの2バイト文字が「"」や「,」と何かに分解されてしまっている可能性も有るかもしれません。
・1つの行中で「"」が偶数個でないと誤動作する可能性はあります。
・CSVファイルに特殊な制御コードになりそうな文字が含まれている。
・これは故意にしているのですが空白だけの行は削除していますが問題ないですよね?

とにかく、こちらではそちらの状況が見えないので、ダメな状況を具体的に提示していただけないと実験などが出来ないのです。もしも具体的な提示が出来ないのならばそう言ってください。あなたの事は無視するようにします。
よろしくお願いいたします。
    • good
    • 0

こんばんは。


#7で回答した者です。

>消えている部位の元データを見てみたのですが、特段ルールが異なるようなことはございませんでした。
>複数のファイルを読み込んだ際に、一部データが消えてしまっている(または取り込めていない)状態です。

よくあることですが、こういう話には、抜けている部分がいくつかあります。
まず、違うOSから吐き出したCSVの場合があります。取り扱う本人が、その辺りについて気がつかないままに、作成依頼しても、九分九厘失敗します。
ファイルは、SJISのようですが、Windows形式の CRLF 改行でしょうか。そこらが違っていると、うまくいくほうがおかしかったりします。

もうひとつは、特別なバイナリコードや誤動作を起こす外字が混じっている可能性があります。テキスト処理するプログラムは、こういう場合は、とても弱いです。

Excelの場合は、Clean 関数というものがありますが、使えるかどうかは不明です。そもそも、VBAで、Clean 関数に頼ること自体が、プログラミングとしては逸脱しているのですが、これは、プリンターを制御したりする、エスケープシーケンスを取り除くための関数でした。それが、適するかは、こちらからでは分かりません。

消えた部分の元ファイルをバイナリで調べてください、と言って分かるでしょうか。もし無理なら、例えば、メモ帳やテキストエディタで、フルテキストが入るかどうかぐらいは調べられるのではないかと思います。その時に、ファイル情報で、UCS-2 (Unicode), UTF-8, SJIS などをチェックします。こういう場合に、特殊なインポートの仕方があります。ただ、正確な情報がないと作れません。

それと、マクロの仕様全体の問題なのですが、連続してインポートするように考えられているようですが、それを、もう一度、1つずつのファイルを入れて、最後尾にインポートをすることにしてみるとか。

CSV は、Excelのファイルの専売特許のように思われがちですが、実際は、Excelでは、最低限のインポートしかしませんから、不具合そのものはしょうがないのです。

最後に、http://excel-ubara.com/ ではQueryTable(外部データの取り込み) の効用を書いているようです。QueryTable で可能になったら、記録マクロから、実際のVBAプログラムに変える方法もあります。また、CSV エディターのようなものが、フリーソフトであります。CSV の中には、特殊信号が含まれているものがあり、本人は、CSVだと信じ込んでいるのですが、実は違っていることがあります。

余談になりますが、私の、掲示板の10年以上の経験では、今回のような一旦不明のトラブルに陥ったCSVのインポートの成功率は、皆無に近いです。それを阻む原因が、質問者さんが、出力のソース元を明らかにしないのと、データをふつうのCSVだと信じ切っていたりすることです。中には、POSシステムの出力データだったりしたこともありました。昔、九天社というところで、そうした処理技術を公開はしていましたが、それは、質問者側から提示されたものが、明らかに、それに該当するものでなくては無理なのです。

それと、Windowsでは、Windowsの中で使えるUnixツールが現在になると、貧弱で使い物にならないことに気が付きました。それで、私個人は、伝家の宝刀として、NotePad++ (テキストエディタ)を利用することにしています。Excelで、インポートし易いように加工しても良いのではないかと思います。回答者は掃いて捨てるほどいるとは思いがちでしょうが、この種のものは、基本的にはだいたい考えていることは同じですから、イレギュラーな問題を解決するには、それなりに、身を切って公開しなければ無理ということもあります。
    • good
    • 0

まさかとは思いますが、複数ファイルの選択方法が判らないと言う事ではありませんよね?


[Shist]キーや[Ctrl]キーを押しながらクリックして選択するのですが、違いとかも判りますよね?
この回答への補足あり
    • good
    • 0

No.11 に対する補足コメントについて



ダメな例と、どのようにダメな結果になったかを提示していただかないとこちらでは調べようがありません。
ちなみに先ほどの例はそちらではどのようになっているのでしょうか?
    • good
    • 0

No.8 に対する補足コメントについて



こちらで実行したら以下のように問題なさそうに取り込めましたがどんなふうにダメなのかを提示してください。

☆1行目
マシン名
2017/08/02
~情報
K22
4/3/2014

☆2行目
マシン名1
2017/08/02
~情報
SN Tr
Stop
C:\wi\Syst\snp.exe
ユーザ名

☆3行目
マシン名2
2017/08/02
~情報
ehmsas.exe
C:\Wi\win\-win5.exe
Ms Cor
6,1,30,1
Ms Sys
2009/07/14
この回答への補足あり
    • good
    • 0

No.8 のさらに追補



「""」を文字列の区切りではなく「"」の文字として扱う事が多いですが、これはそんなこと考えていません「"」がただ2つあるとして扱います。
    • good
    • 0

No.8 追補



Chr(34) は「"」です。
Chr(39) は「'」です。
Chr(44) は「,」です。
    • good
    • 0

チョットしかテストしていませんがお試しください。


-------------------------------------------------------------------------------------------
Sub Sample()
Dim CsvFile As Variant
Dim FileName As Variant
Dim FileNo As Variant
Dim RowData As String
Dim ColumnData As String
Dim RowNo As Long
Dim ColumnNo As Long
Dim Character As Boolean
Dim Position As Long
Cells.Delete Shift:=xlUp
ChDir ThisWorkbook.Path
CsvFile = Application.GetOpenFilename(FileFilter:="CSV ファイル (*.csv),*.csv", MultiSelect:=True)
If IsArray(CsvFile) Then
For Each FileName In CsvFile
FileNo = FreeFile
Open FileName For Input As #FileNo
Do Until EOF(FileNo)
Line Input #FileNo, RowData
RowData = Trim(RowData)
If RowData <> "" Then
RowNo = RowNo + 1
ColumnNo = 1
For Position = 1 To Len(RowData)
If Mid(RowData, Position, 1) = Chr(34) Then
Character = Not Character
If Character Then ColumnData = Chr(39)
Else
If Mid(RowData, Position, 1) = Chr(44) Then
If Character Then
ColumnData = ColumnData & Mid(RowData, Position, 1)
Else
Cells(RowNo, ColumnNo).Value = ColumnData
ColumnData = ""
ColumnNo = ColumnNo + 1
End If
Else
ColumnData = ColumnData & Mid(RowData, Position, 1)
End If
End If
Next
Cells(RowNo, ColumnNo).Value = ColumnData
ColumnData = ""
ColumnNo = 0
End If
Loop
Close #FileNo
Next
End If
End Sub
-------------------------------------------------------------------------------------------
※ 一度保存してから実行してください。
この回答への補足あり
    • good
    • 0

こんばんは。



この前から書かれている「データ内」という意味がやっと分かりました。
私は、てっきり途中から、CSV が始まるものだと思いました。
文字列内という意味だったのですね。
叩き台として、このコードを出しておきます。

'//標準モジュール
Sub CsvImport()
'CSVファイルの読み込み
 Dim CsvFileNames As Variant
 Dim txtLine As String
 Dim Bf() As String
 Dim lastRow As Long
 Dim Sh As Worksheet
 Dim FlNo As Integer
 Dim i As Long, f As Variant
 
 With ThisWorkbook 'シート&パスの設定
  Set Sh = .ActiveSheet
  ChDrive .Path
  ChDir .Path
 End With
 '複数のファイルの選択を可に設定
 CsvFileNames = Application.GetOpenFilename _
   (filefilter:="CSVファイル(*.csv),*.csv", _
   Title:="CSVファイル選択", MultiSelect:=True)
 If VarType(CsvFileNames) = vbBoolean Then Exit Sub 'キャンセル時の処置
 
 lastRow = Cells(Rows.Count, 1).End(xlUp).Row + 1 '行の初期値
 i = i + lastRow
 For Each f In CsvFileNames 'ファイル数分ループ
   FlNo = FreeFile()
  Open f For Input As #FlNo
  Do Until EOF(FlNo) '最終行までループ
   Line Input #FlNo, txtLine '一行読み込み
   If Len(Trim(txtLine)) > 0 Then
   If InStr(1, txtLine, """") > 0 Then
   txtLine = REReplace(txtLine)
   End If
   Bf = Split(txtLine, ",") 'カンマで分割し配列に代入
    With Sh '1行分のデータをセルに出力
     .Cells(i, 1).Resize(, UBound(Bf) + 1).Value = Bf
    End With
   End If
   i = i + 1
  Loop
  Close #FlNo
 Next
End Sub
Function REReplace(enter_text)
Dim RegEx As Object
Dim Ms
Set RegEx = CreateObject("VBScript.RegExp")
Dim ret As String, rep As String
With RegEx
  .Global = True: .IgnoreCase = False: .MultiLine = True
  .Pattern = "("".*,.*"")"
 Set Ms = .Execute(enter_text)
End With
   ret = Ms(0).SubMatches(0)
   rep = Replace(ret, ",", "")
   rep = Replace(rep, """", "")
  REReplace = Replace(enter_text, ret, rep)
End Function
    • good
    • 0

No.6 の追加(以下も考えられますね)



例 1-3:「123,45,"678,90"」→「123」「45」「"678,90"」
例 1-4:「123,45,"678,90"」→「123」「45」「678,90」
    • good
    • 0

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