質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

1回答

1114閲覧

【VBA】CSVファイル出力マクロでShift-JISからUTF-8に書き直したい

koburon

総合スコア29

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2023/02/06 07:15

編集2023/02/07 06:15

前提

VBAでPostgreSQLのテーブル「t_社員マスタ」にインポートするCSVファイルを出力するマクロを作っています。

該当のソースコード

VBA

1Sub writeCSV() 2 Dim ws As Worksheet 3 Dim maxrow As Long 4 Dim fileNo As Integer 5 Dim wrow As Long 6 Dim wcol As Long 7 Dim i As Long 8 Dim val As String 9 Dim out_line As String 10 Const stCol = 1 11 Const enCol = 144 12 Dim arrVal(enCol - stCol) As String 13 Set ws = Worksheets("Sheet1") 14 maxrow = ws.Cells(Rows.Count, 1).End(xlUp).Row 15 fileNo = FreeFile 16 17 Application.ScreenUpdating = False 18 19 ' ---------------------------- 20 ' ファイルの出力処理 21 ' ---------------------------- 22 Dim myFileName, fileName, fileDateNm As String 23 24 ' ファイル名を作成する 25 fileDateNm = Replace(CStr(Date), "/", "") 26 fileName = "社員マスタ更新データ_" & fileDateNm 27 ' ダイアログ表示 28 myFileName = Application.GetSaveAsFilename(InitialFileName:=fileName, FileFilter:="CSV ファイル (*.csv),*.csv") 29 ' キャンセルなら終了 30 If myFileName = "False" Then 31 Exit Sub 32 End If 33 ' 保存 34 Open myFileName For Output As #fileNo 35 For wrow = 3 To maxrow 36 i = 0 37 For wcol = stCol To enCol 38 '1データ取得 39 val = ws.Cells(wrow, wcol).Value 40 'データをダブルクオートでくくり、配列へ格納 41 arrVal(i) = wrap_data(val) 42 i = i + 1 43 Next 44 'カンマで連結 45 out_line = Join(arrVal, ",") 46 Print #fileNo, out_line 47 Next 48 Close #fileNo 49 50 MsgBox ("CSVファイルを「Shft_JIS」で出力しました。レコード部分のみ出力しています。") 51 52 Application.ScreenUpdating = True 53End Sub 54 55'入力文字列をダブルクオートでくくる 56Private Function wrap_data(ByVal val As String) As String 57 wrap_data = """" & val & """" 58End Function

発生している問題・エラーメッセージ

上記コードで「Shft_JIS」形式のCSVが出来ましたが、SQL上でCOPYコマンドを実行したところ、以下のエラーメッセージが出ました。

COPY t_社員マスタ FROM '/public/csv/社員マスタ更新データ_20230206.csv' CSV ERROR: 符号化方式"UTF8"で無効なバイトシーケンスです: 0x8d CONTEXT: t_社員マスタ_マクロテストのCOPY。行番号 1

実現したいこと

UTF-8でないと受付ないという意味だと思うので、上記コードを書き換えて「utf-8」形式のCSVを出力させたいです。

試したこと

下記URLを参考にし、コードを作成し直そうと思っています。
サンプルプログラムでは、ADODB.Streamオブジェクトを

  1. 生成
  2. 文字コード設定
  3. オープン
  4. 1行ずつ文字列を流し込む
  5. CSVに保存
  6. クローズ

という流れで作成するイメージは理解できましたが、元のコードで既に「Open myFileName」とオープンを宣言してしまっています。
Openをどのように書き直せば、UFF-8に設定できるようになるでしょうか?
あるいは、他に参考になるURLなどがあれば教えていただければ幸いです。
よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

PC:Windows11
ソフト:Microsoft365 Excel
PostgreSQLのバージョン:9.0.1
PSql Editのバージョン:5.2.3.9
参考URL:エクセルVBAで文字コードUTF-8のCSVファイルを書き出す方法

コメントを受けて追記

下記のようにsjisを設定してみましたが、encodingの近辺の構文エラーとだけ表示され、具体的にどこがエラーなのかよく分からないです。

COPY t_社員マスタ FROM '/public/csv/社員マスタ更新データ_20230206.csv' with encoding 'sjis' csv; ERROR: "encoding"またはその近辺で構文エラー LINE 1: ...lic/csv/社員マスタ更新データ_20230206.csv' with encoding '...

以前にもこのサイトで同じような質問があったので確認しましたが、postgreSQLのサーバー上にCSVを保存してありますが、うまくいかないです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

UTF-8でないと受付ない

Postgresql の COPY コマンドですがオプションを指定すれば SJIS のファイルでインポートも行えるようです。

■ Postgresql 9.1のCOPYでファイルの文字コードを指定する
https://symfoware.blog.fc2.com/blog-entry-942.html

COPY t_社員マスタ FROM '/public/csv/社員マスタ更新データ_20230206.csv' WITH encoding 'SJIS' CSV

Openをどのように書き直せば、UFF-8に設定できるようになるでしょうか?

どうしても VBA で行いたいということであれば、こちらをどうぞ。

VBA

1Option Explicit 2 3' StreamTypeEnum 4Const adTypeBinary = 1 5Const adTypeText = 2 6 7' LineSeparatorsEnum 8Const adCR = 13 9Const adCRLF = -1 10Const adLF = 10 11 12' StreamWriteEnum 13Const adWriteChar = 0 14Const adWriteLine = 1 15 16' SaveOptionsEnum 17Const adSaveCreateNotExist = 1 18Const adSaveCreateOverWrite = 2 19 20Sub writeCSV() 21 Dim ws As Worksheet 22 Dim maxrow As Long 23 Dim fileNo As Integer 24 Dim wrow As Long 25 Dim wcol As Long 26 Dim i As Long 27 Dim val As String 28 Dim out_line As String 29 Const stCol = 1 30 Const enCol = 2 ' 144 31 Dim arrVal(enCol - stCol) As String 32 Set ws = Worksheets("Sheet1") 33 maxrow = ws.Cells(Rows.Count, 1).End(xlUp).Row 34 fileNo = FreeFile 35 36 Application.ScreenUpdating = False 37 38 ' ---------------------------- 39 ' ファイルの出力処理 40 ' ---------------------------- 41 Dim myFileName, fileName, fileDateNm As String 42 43 ' ファイル名を作成する 44 fileDateNm = Replace(CStr(Date), "/", "") 45 fileName = "社員マスタ更新データ_" & fileDateNm 46 ' ダイアログ表示 47 myFileName = Application.GetSaveAsFilename(InitialFileName:=fileName, FileFilter:="CSV ファイル (*.csv),*.csv") 48 ' キャンセルなら終了 49 If myFileName = "False" Then 50 Exit Sub 51 End If 52 53 54 Dim stream 55 Set stream = CreateObject("ADODB.Stream") 56 57 stream.Charset = "UTF-8" 58 stream.LineSeparator = adLF 59 60 61 ' 保存 62 'Open myFileName For Output As #fileNo 63 stream.Open 64 For wrow = 3 To maxrow 65 i = 0 66 For wcol = stCol To enCol 67 '1データ取得 68 val = ws.Cells(wrow, wcol).Value 69 'データをダブルクオートでくくり、配列へ格納 70 arrVal(i) = wrap_data(val) 71 i = i + 1 72 Next 73 'カンマで連結 74 out_line = Join(arrVal, ",") 75 'Print #fileNo, out_line 76 stream.WriteText out_line, adWriteLine 77 Next 78 79 stream.Position = 0 'ストリームの位置を0にする 80 stream.Type = adTypeBinary 'データの種類をバイナリデータに変更 81 stream.Position = 3 'ストリームの位置を3にする 82 83 Dim byteData() As Byte '一時格納用 84 byteData = stream.Read 'ストリームの内容を一時格納用変数に保存 85 stream.Close '一旦ストリームを閉じる(リセット) 86 87 stream.Open 'ストリームを開く 88 stream.Write byteData 'ストリームに一時格納したデータを流し込む 89 90 91 'Close #fileNo 92 stream.SaveToFile myFileName, adSaveCreateOverWrite 93 stream.Close 94 95 96 MsgBox ("CSVファイルを「UTF-8」で出力しました。レコード部分のみ出力しています。") 97 98 Application.ScreenUpdating = True 99End Sub 100 101'入力文字列をダブルクオートでくくる 102Private Function wrap_data(ByVal val As String) As String 103 wrap_data = """" & val & """" 104End Function

少しハマった箇所としては、参考 URL にあったやり方だと UTF-8 出力時に BOM が付いてしまうというのがハマリどころでした。
下記を参考に BOM を除去するようにしてあります。

■ エクセルVBAでBOM無しのUTF-8でCSVファイルなどを出力する方法
https://tonari-it.com/excel-vba-utf8n-bom/

投稿2023/02/06 11:48

cx20

総合スコア4633

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koburon

2023/02/07 00:39

>cx20様 回答ありがとうございます。 コメントいただいた通りCOPYコマンドを実行したところ、WITH encoding の近辺でエラーが発生しました。 現在、PostgreSQL用のSQLエディタとしてPSqlEditのバージョン5.2.3.9を使用していますが、古いため実装されていないのでしょうか。
cx20

2023/02/07 21:36 編集

> ERROR: "encoding"またはその近辺で構文エラー なんとなく「encoding」の指定がダメと言われている感じですね・・ > PSqlEditのバージョン5.2.3.9 ツールそのものよりもDB接続に使用しているライブラリ(libpq.dll)のバージョンの問題の気もしますが、 ツールが2004年のようですので、もしかしたら「encoding」をサポートしていない、ということもあるのかもしれません。 PostgreSQL 環境が手元に無いので試せないですが、 psql コマンドではどうでしょうか? 以下、psql コマンドの使用例になります。 ■ RDS for PostgreSQL で SJISのCSVファイルをインサートする https://dev.classmethod.jp/articles/rds-for-postgresql-sjis-csv-insert/
cx20

2023/02/07 21:33 編集

それと「encoding」の指定は、DBサーバー側とクライアント側で変換がサポートされている必要があります。 サポートされた組み合わせか否かは下記のコマンドで確認できるようです。(PostgreSQLに詳しくないので参考情報まで。) 「sjis_to_utf8」が表示されるようであれば、変換はサポートされているのだと思います。 ■ PostgreSQL の搭載機能 / 自動エンコーディング変換の使い方 / P8 / LIST5:pg_conversion表 https://pr.biprogy.com/solution/tec/atlasbase/s33drt000005ei89-att/dbm_1001_postresql.pdf select * from pg_conversion where conname like '%sjis%' limit 10; 実行例) https://onecompiler.com/postgresql/3yx8wxguy Output: oid | conname | ------+----------------+ 4522 | sjis_to_utf8 |
koburon

2023/02/09 01:01 編集

>サポートされた組み合わせか否か コマンドを実行したところ、以下の結果になりました。 utf8からsjisへの変換はサポートされているようです。 Output: name| namespace | owner | default | ------+-------------+--------+--------+ euc_jp_to_sjis | 11 | 10 | t| sjis_to_euc_jp | 11 | 10 | t| sjis_to_mic | 11 | 10 | t| mic_to_sjis | 11 | 10 | t| sjis_to_utf8 | 11 | 10 | t| utf8_to_sjis | 11 | 10 | t|
koburon

2023/02/09 09:11 編集

>ENCODING オプションは 9.1 以降でしか使用できないのかもしれません。 その可能性はありますね。 元のコードでShft_JISではき出した後、excelで「CSV UTF-8」で保存したものでCOPYすると成功したので、 今回はVBAの段階でUTF-8に出力するようにしようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問