Excel (VBA)

Excel VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(Windows 10 Pro : Microsoft 365)
UTF-8の文字コードでのcsv出力不具合
投稿日時: 23/01/14 23:21:46
投稿者: suvalu

外部システムからダウンロードしたcsv(UTF-8)を、querytableで読み込み表示形式を変更し、
別システムへアップロードするcsvとして保存するマクロを作成したいのですが、
UTF-8の文字コードでcsv保存はできるのですが、それをインポートウィザードで開いた際に、
もとのcsvにはAI列までしかデータがないにも関わらず、AJ列〜AN列の1行目に「_1」「_2」...といったよくわからない文字列が追加されていまいます。
解消法はありますでしょうか。
 
 

Option Explicit

Sub con()
   
    Dim Ws As Worksheet
    Dim wb As Workbook
    Dim wbs As Worksheet
    Dim Qt As QueryTable
    Dim AAAAA As Variant
    Dim Path As String
    Dim Exp As String
    Dim FolderDate As Variant
    Dim FolderPath As Variant
    Dim FileName As Variant
    Dim r As Long
    
    FolderDate = Format(Date, "yyyymmdd")
    FileName = "xxx"
    FolderPath = "C:\Users"

    

    Application.ScreenUpdating = False
    

 
   AAAAA = Application.GetOpenFilename("CSVファイル(*.csv),*.csv")
    If AAAAA = "False" Then Exit Sub
    
    Path = "TEXT;" & AAAAA

Set wb = Workbooks.Add
Set wbs = ActiveSheet


    Set Qt = wbs.QueryTables.Add(Connection:=Path, Destination:=wbs.Range("A1:AI100")) ' CSV を開く
    With Qt
        .TextFilePlatform = 65001          ' 文字コードを指定
        .TextFileParseType = xlDelimited ' 区切り文字の形式
        .TextFileCommaDelimiter = True   ' カンマ区切り
        .TextFileColumnDataTypes = Array(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)
        .RefreshStyle = xlOverwriteCells ' セルに上書き
        .Refresh                         ' データを表示
        .Delete                          ' CSV との接続を解除
    End With
    
    With ActiveSheet
    .Range("C:C").NumberFormatLocal = "yyyy-mm-dd"

    End With
    
    Dim i As Long
    Dim j As Long
    Dim strList As String
    Dim adoSt As Object
    Set adoSt = CreateObject("ADODB.Stream")
    With adoSt
        .Type = adTypeText
        .Charset = "UTF-8"
        .Open
    End With
    With ActiveSheet.UsedRange
        For i = 1 To .Rows.Count
            strList = ""
            For j = 1 To 35
                If j > 1 Then
                    strList = strList & ","
                End If
                strList = strList & .Cells(i, j)
            Next
            adoSt.WriteText strList, adWriteLine
        Next
    End With
    
    
    r = 1
    
    Do Until Dir("C:\Users" & "\" & FileName & "_" & FolderDate & ".csv") = ""
    FolderDate = FolderDate & "_" & r
    r = r + 1
    Loop
    
    adoSt.SaveToFile "C:\Users" & "\" & FileName & "_" & FolderDate & ".csv", adSaveCreateOverWrite
    adoSt.Close
    Set adoSt = Nothing
    
    ActiveWorkbook.Close saveChanges:=False
 Application.ScreenUpdating = True
    
End Sub

回答
投稿日時: 23/01/15 07:33:36
投稿者: simple

同様のデータをこちらは持ち合わせていないので、残念ながら希望される直接の回答では
ありません。いくつか確認をさせて頂きたい。
 
CSVを読み込んで、もう一度保存しているのは、
日付形式の変更のためという理解でいいのですか?
テキストとして読み込んで、それは実現できているんですか?
(異常事象と直接の関係は無いと思いますが、話の前提として。)
 
>UTF-8の文字コードでcsv保存はできるのですが、それをインポートウィザードで開いた際に、・・
とのこと。
(1)提示されたコードで作成されたCSVファイルを、テキストエディターで開いて
   確認されていますか?
   一行目のデータは正常に35個のデータがカンマ区切りで作成されていますか?
(2)インポート先のシートは何か特別なものですか?
   まったくの新規シートにインポートしても同様の事象が起きますか?
 (インポート処理にもし問題があるなら、その動作をマクロ記録して提示されると、
  なにか手がかりが掴めるかもしれませんね。)
 
なお、CSV保存は、
CSV UTF-8(カンマ区切り)の形式で直接保存することもできると思いますが、
ADODB.Streamを使う何か必然性があるんでしょうか?

投稿日時: 23/01/15 12:32:35
投稿者: suvalu

引用:
CSVを読み込んで、もう一度保存しているのは、
日付形式の変更のためという理解でいいのですか?
テキストとして読み込んで、それは実現できているんですか?
(異常事象と直接の関係は無いと思いますが、話の前提として。)

 
引用:
(1)提示されたコードで作成されたCSVファイルを、テキストエディターで開いて
   確認されていますか?
   一行目のデータは正常に35個のデータがカンマ区切りで作成されていますか?

 
やりたいこととしては、システムAからダウンロードしたcsvを、0落ち回避のためquerytableで読み込み、
C列に日付が入っており(yyyy/mm/dd hh:mm:ss)、これをISO8601形式の日時表示に変更したものを
別名保存で指定のディレクトリに保存し、システムBへアップロードしたいです。
テキストエディターでは問題なく表示されておりますが、保存したcsvをインポートウィザードから確認するとISO8601形式になっていません。
 
引用:
なお、CSV保存は、
CSV UTF-8(カンマ区切り)の形式で直接保存することもできると思いますが、
ADODB.Streamを使う何か必然性があるんでしょうか?

 
こちらSaveAsでFileFormatをxlCSVUTF8にして保存してみたのですが、この方法だと文字化けを起こしてしまいます。

回答
投稿日時: 23/01/15 13:31:03
投稿者: simple

(1)元々のデータの一行目のデータの値のなかにカンマそのものがあると、
   今の書き方だと再度インポートしたときに、35列以上になったりしませんか?
(2)もともとの日付はシート上できちんと変換されていることを確認されていますか?
   ・.TextFileColumnDataTypeをすべて2ではなく、日付けに相当する列は
      例えば xlYMDFormat(5ですか)といったものにしないと、
      日付として読み込まれていないのでは?
      (時刻も入っているのですか? 試していませんが標準で読み込むとか)
   ・"yyyy-mm-dd"形式に変換して、
   ・.Cells(i, j).Textを連結する
   ようにしてはどうですか?

投稿日時: 23/01/15 13:46:45
投稿者: suvalu

(1)元々のデータの一行目のデータの値のなかにカンマそのものがあると、
   今の書き方だと再度インポートしたときに、35列以上になったりしませんか?
 
→一行目は見出し項目で、AI列までデータが入っており、テキストエディターではカンマそのものも存在します。
ADODB.Streamの記述に問題があるのでしょうか?
 
(2)もともとの日付はシート上できちんと変換されていることを確認されていますか?
   ・.TextFileColumnDataTypeをすべて2ではなく、日付けに相当する列は
      例えば xlYMDFormat(5ですか)といったものにしないと、
      日付として読み込まれていないのでは?
      (時刻も入っているのですか? 試していませんが標準で読み込むとか)
 
→時刻も入っております。システムBに読み込む際にはyyyy-MM-ddTHH:mm:ssで読み込まないとエラーが返されてしまいます。
 
   ・"yyyy-mm-dd"形式に変換して、
   ・.Cells(i, j).Textを連結する
   ようにしてはどうですか?
 
→こちらはどこの記述のことをおっしゃっていますか?[/quote]

回答
投稿日時: 23/01/15 14:26:35
投稿者: simple

(1)
"aa,bb",cc
という2列のデータだとすると、
単純にカンマで連結すると、
aa,bb,cc
という3列のデータになりませんか、という話です。
 
(2)
>→こちらはどこの記述のことをおっしゃっていますか?
書式の変換は変更不要です。

strList = strList & .Cells(i, j)

strList = strList & .Cells(i, j).Text
に変更してはという意味です。
(日付以外の他の項目に影響があるなら、別途の対応が必要になるかもしれません)
 
途中経過を観察して、適切な日付形式として保存されているか、確認してはどうですか?

投稿日時: 23/01/15 14:52:12
投稿者: suvalu

ありがとうございます。
 
 

引用:
書式の変換は変更不要です。
strList = strList & .Cells(i, j)

strList = strList & .Cells(i, j).Text
に変更してはという意味です。
(日付以外の他の項目に影響があるなら、別途の対応が必要になるかもしれません)

 
こちらではファイル自体が文字化けするようで解決しませんでした。
 
↓このような書き方でも変わらなかったのですが、querytable上で変換するやり方はあるのでしょうか。
.TextFileColumnDataTypesは2でも5でも結果は変わりません。
 
    ActiveSheet.Range("C:C").Select
    With Selection
    .NumberFormatLocal = "YYYY-MM-DDTHH:MM:SSZ"
    End With[

 
 
なお、
            Next
            adoSt.WriteText strList, adWriteLine
        Next
    End With

の書き込みまででブレークポイントすると、処理中のエクセルには想定通りの書き込みができています。
保存後もテキストエディターでは表示に問題はないのですが、エクセルで再度PowerQueryから開くと
別の列の値が0落ち(電話番号です))していたり、日付の表示形式がもとに戻ってしまいます。

回答
投稿日時: 23/01/15 17:10:47
投稿者: simple

引用:
の書き込みまででブレークポイントすると、処理中のエクセルには想定通りの書き込みができています。

いえ、シートの値が問題ではなくて、そうではなくて
・連結した結果のstrListがどうかということかと思います。
・それを保存したCSVファイルをテキストエディターで確認した結果、
  日付はどうなっているのですか?
・その後のインポートの結果はどうですか?
など、ステップごとに確認されたらいかがですか?
その確認結果によって、すべきことが明確になります。
 
# 外出しますので、他の回答者さんの回答をお待ちください。

回答
投稿日時: 23/01/16 11:35:57
投稿者: simple

重複もありますが、懸念点をもう一度書きますので、よく検証してみてください。
 
(1)一行目の列数が異なり、_1や_2といったものが表示される。
⇒一行目について、CSVファイルと得られた結果のCSVを要素ごとに突合せして下さい。
  一致していないところはどこかを精査してください。(印刷して確認するのが望ましい)
  ・区切り文字としてのカンマではなく、値そのものにカンマが含まれていないか、
  ・カンマとは別の区切り文字で区切られていないか、等を確認してください。
   
(2)日付の形式が想定したものにならない点。
  これも事実関係をもう一度確認してください。
  ・インポートした直後にセルの書式が文字列になっていると、
    "yyyy-mm-dd"への書式変更はできないはずです。(日付形式で読む必要があります)
  ・ステップ実行して、C列の"yyyy-mm-dd"への書式変更が有効に実行されているか
    確認してください。
  ・ステップ実行して、
      adoSt.WriteText strList, adWriteLine
      の実行直前のstrListが意図した日付形式になっているか確認。
 
(3)できあがったCSVファイルの確認について。
 
> 保存後もテキストエディターでは表示に問題はないのですが、
> エクセルで再度PowerQueryから開くと、
> 別の列の値が0落ち(電話番号です))していたり、
> 日付の表示形式がもとに戻ってしまいます。

 
  PowerQueryで開くというのはquerytableで読み込むのとは違うのですね。
  Excelのお節介機能?で形式等が自動変換されている恐れがあります。
   
  なお、querytable(「テキストから(レガシ)」を使用)で読み込む場合、
  日付は"yyyy-mm-dd"で読み込むことはできない仕様のようです。
  YMD形式を指定して読み込むと、yyyy/m/d形式で読み込まれます。
   
  もともと、別のシステムに投入する目的ですから、Excelに読み込んで確認しても
  意味が乏しい。テキストとして確認すれば十分です。

トピックに返信