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

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

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

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

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

1回答

1494閲覧

【VBA】PostgreSQLにインポートできるようにCSVファイルを作成したい

koburon

総合スコア31

VBA

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

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

0クリップ

投稿2023/01/27 01:11

前提

VBAでCSVファイルを出力するマクロを作っています。
CSVファイルはPostgreSQLの社員マスタにインポートできるように形式を調整して作成します。下記URLを参考にしています。
【超簡単】ワンタッチでエクセルからCSV出力するVBAプログラム
PostgreSQLでCSVファイルをインポート/エクスポートする方法

該当のソースコード

全てのセル値を「""」で囲んでCSV出力するコードです。

VBA

1Option Explicit 2 3Const EXT As String = ".csv" 4 5Sub CSV出力_詳細指定() 6 Dim Filepath As String 7 Filepath = Application.GetSaveAsFilename(, "CSVファイル(*.csv),*.csv") 8 9 If Filepath = "False" Then 10 End 11 End If 12 13 Call csv.Output(TargetSheet:=ActiveSheet, Filepath:=Filepath, _ 14 StartRow:=3, StartCol:=1, _ 15 WithQuoteCols:=GetSequence(1, 144), _ 16 Charset:="utf-8") 17 18 MsgBox "CSVファイルを「utf-8」で出力しました。レコード部分のみ出力しています。" 19End Sub

GetSequence

1Public Function GetSequence(minNum As Long, maxNum As Long) As String 2 Dim i As Long 3 For i = minNum To maxNum 4 GetSequence = GetSequence & "," & i 5 Next 6 GetSequence = Mid(GetSequence, 2) 7End Function

モジュール「csv.Output」の中身です。

csv.Output

1Option Explicit 2 3'この標準モジュールは変更しない 4 5Enum CSVCols 6 Default = 0 '当初設定に従う 7 force = 1 '強制的に処理を行う 8 Ignore = 2 '処理を行わない 9End Enum

Output

1'CSV出力メインロジック 2'正常終了時TRUEを返す ※現状は、エラー処理を行っていないので常にTRUEが返る 3'※charset に utf-8n と指定すると「BOMなしUTF-8」でCSVデータを作成する 4Function Output(TargetSheet As Worksheet, ByVal Filepath As String, _ 5 Optional ByVal StartRow As Long = 1, Optional ByVal EndRow As Long = 0, _ 6 Optional ByVal StartCol As Long = 1, Optional ByVal EndCol As Long = 0, _ 7 Optional ByVal WithFormatCols As String = "", Optional ByVal WithoutFormatCols As String = "", _ 8 Optional ByVal WithQuoteCols As String = "", Optional ByVal WithoutQuoteCols As String = "", _ 9 Optional ByVal Delimitar As String = ",", Optional ByVal LineEndingCode As String = vbCr & vbLf, _ 10 Optional ByVal QuoteChar As String = """", Optional ByVal CharReplaceQuote As String = """""", _ 11 Optional ByVal Charset As String = "shift_jis") As Boolean 12 13 '出力範囲(行)の指定 14 If EndRow = 0 Then 15 EndRow = getLastRow(TargetSheet) 16 End If 17 18 '出力範囲(列)の設定 19 If EndCol = 0 Then 20 EndCol = getLastColumn(TargetSheet) 21 End If 22 23 '各列出力時の書式付きかどうかの処理方法を配列に格納 24 Dim FormatOptionOfColumns() As Long 25 FormatOptionOfColumns = setOption(WithFormatCols, WithoutFormatCols, StartCol, EndCol) 26 27 '各列出力時に”で囲むかどうかの処理方法を配列に格納 28 Dim QuoteOptionOfColumns() As Long 29 QuoteOptionOfColumns = setOption(WithQuoteCols, WithoutQuoteCols, StartCol, EndCol) 30 31 'CSV出力データ準備 32 Dim csvData As String 33 34 Dim rowData() As String 35 ReDim rowData(0 To EndCol - StartCol) As String 36 37 Dim R As Long 38 Dim c As Long 39 For R = StartRow To EndRow 40 For c = StartCol To EndCol 41 rowData(c - StartCol) = convertFormatTowriteCSVFile(TargetSheet.Cells(R, c), StartCol, _ 42 Delimitar, QuoteChar, CharReplaceQuote, _ 43 FormatOptionOfColumns, QuoteOptionOfColumns) 44 Next 45 46 '1行のデータをデリミタ(区切り文字)でつないで、改行を付加 47 csvData = csvData & Join(rowData, Delimitar) & LineEndingCode 48 Next 49 50'csv出力 51 Output = writeCSVFile(csvData, Filepath, Charset) 52 53End Function

getLastRow

1Private Function getLastRow(TargetSheet As Worksheet) As Long 2 Dim Row As Long 3 Dim Column As Long 4 5'UsedRangeで取得した最下行の右→左、最下行の1段上の右→左と走査していく 6 For Row = TargetSheet.UsedRange.Row + TargetSheet.UsedRange.Rows.Count - 1 To 1 Step -1 7 For Column = TargetSheet.UsedRange.Column + TargetSheet.UsedRange.Columns.Count - 1 To 1 Step -1 8 If TargetSheet.Cells(Row, Column).Value <> "" Then 9 GoTo Finally 10 End If 11 Next 12 Next 13 14Finally: 15 getLastRow = Row 16End Function

getLastColumn

1Private Function getLastColumn(TargetSheet As Worksheet) As Long 2 Dim Row As Long 3 Dim Column As Long 4 5'UsedRangeで取得した最右行の下→上、最右行の1列左の下→上と走査していく 6 For Column = TargetSheet.UsedRange.Column + TargetSheet.UsedRange.Columns.Count - 1 To 1 Step -1 7 For Row = TargetSheet.UsedRange.Row + TargetSheet.UsedRange.Rows.Count - 1 To 1 Step -1 8 If TargetSheet.Cells(Row, Column).Value <> "" Then 9 GoTo Finally 10 End If 11 Next 12 Next 13 14Finally: 15 getLastColumn = Column 16End Function

setOption

1'CSV出力時のオプション 2'(1.書式付で出力するか、2.「”」で囲むかについての設定) 3'を使いやすい形(配列)に格納する 4Private Function setOption(WithCols As String, WithoutCols As String, minCol As Long, maxCol As Long) 5 WithCols = "," & WithCols & "," 6 WithoutCols = "," & WithoutCols & "," 7 8 Dim ret() As Long 9 ReDim ret(0 To maxCol - minCol) 10 11 Dim c As Long 12 For c = LBound(ret) To UBound(ret) 13 If InStr(WithCols, "," & c + 1 & ",") Then 14 ret(c) = CSVCols.force 15 ElseIf InStr(WithoutCols, "," & c + 1 & ",") Then 16 ret(c) = CSVCols.Ignore 17 Else 18 ret(c) = CSVCols.Default 19 End If 20 Next 21 22 setOption = ret 23End Function

convertFormatTowriteCSVFile

1'各セルの値をCSV出力用に加工する 2Private Function convertFormatTowriteCSVFile(R As Range, BaseCol As Long, _ 3 Delimitar As String, QuoteChar As String, CharReplaceQuote As String, _ 4 FormatOptionOfColumns() As Long, QuoteOptionOfColumns() As Long) 5 Dim Val As Variant 6 Val = R.Value 7 8 '書式を適用 9 If FormatOptionOfColumns(R.Column - BaseCol) = CSVCols.force Or _ 10 FormatOptionOfColumns(R.Column - BaseCol) = CSVCols.Default And addFormat(Val) Then 11 Val = R.Text 12 End If 13 14 '「”」で囲む ※データ中に「”」があれば、指定の値に置き換える 15 If QuoteOptionOfColumns(R.Column - BaseCol) = CSVCols.force Or _ 16 QuoteOptionOfColumns(R.Column - BaseCol) = CSVCols.Default And AddQuote(Val, Delimitar, QuoteChar) Then 17 Val = QuoteChar & Replace(Val, QuoteChar, CharReplaceQuote) & QuoteChar 18 End If 19 20 convertFormatTowriteCSVFile = Val 21End Function

addFormat

1'CSVCols.Defaultの場合に、書式を適用するかどうかの判定 2Private Function addFormat(Val As Variant) As Boolean 3 addFormat = False 4End Function

AddQuote

1'CSVCols.Defaultの場合に、「”」で囲むかの判定。 2Private Function AddQuote(Val As Variant, Delimitar As String, QuoteChar As String) As Boolean 3 If InStr(Val, Delimitar) Or InStr(Val, QuoteChar) Or _ 4 InStr(Val, vbLf) Or InStr(Val, vbCr) Then 5 AddQuote = True 6 Else 7 AddQuote = False 8 End If 9End Function

writeCSVFile

1'CSVデータ出力 2'正常終了時TRUEを返す 3Private Function writeCSVFile(csvData As String, Filepath As String, Charset As String) As Boolean 4 Dim removeBom As Boolean 5 6 If Charset = "utf-8n" Then 7 Charset = "utf-8" 8 removeBom = True 9 Else 10 removeBom = False 11 End If 12 13'本来は、下記で変数宣言したいが、参照設定しない場合のために、変数宣言をObjectにする 14' Dim ST As ADODB.Stream 15 Dim ST As Object 16 Set ST = CreateObject("ADODB.stream") 17 18 With ST 19 .Mode = 3 'adModeReadWrite 20 .Type = 2 'adTypeText 21 .Charset = Charset 22 23 .Open 24 .WriteText csvData, 0 'adWriteChar 25 End With 26 27 If removeBom Then 28'以下、Bom抜き処理 29'BOM部分を読み飛ばして、その先から読み込む 30 ST.Position = 0 31 ST.Type = 1 'adTypeBinary 32 ST.Position = 3 33 34'別のストリームにバイナリとしてコピー 35' Dim ST2 As ADODB.Stream 36 Dim ST2 As Object 37 Set ST2 = CreateObject("ADODB.stream") 38 39 With ST2 40 .Mode = 3 'adModeReadWrite 41 .Type = 1 'adTypeBinary 42 .Open 43 44 .Write ST.Read 45 46 .SaveToFile Filepath, 2 'adSaveCreateOverWrite 47 .Close 48 End With 49 Else 50 ST.SaveToFile Filepath, 2 'adSaveCreateOverWrite 51 End If 52 53 ST.Close 54 writeCSVFile = True 55End Function

インポートするテーブルのソースです。文字数制限のため一部のみ記載していますが、文字コードは"メールアドレス"のtextを除き、全てcharacterです。

t_社員マスタ

1CREATE TABLE public."t_社員マスタ" ( 2 "社員番号" character(8) NOT NULL, 3 "氏名" character(16), 4 "氏名カナ" character(24), 5 "生年月日" character(8), 6  ・ 7  ・ 8  ・ 9 "メールアドレス" text 10); 11ALTER TABLE ONLY public."t_社員マスタ" 12 ADD CONSTRAINT "t_社員マスタ_pkey" PRIMARY KEY ("社員番号");

発生している問題

上記のコードでCSVファイルは問題なく出力されますが、コードを社内でレビューを行った際、Openメソッドを使って出力する方法はできませんか、という修正依頼を受けました。

実現したいこと

・「csv.Output」を「Openメソッド」でCSV出力するように書き換える
・CSVファイルの文字コードは全てShift-JISにする

試したこと

VBAコードで「utf-8」を「Shift-JIS」に全て置き換えて実行したところエラーは起きませんが、t_社員マスタに正しく格納できるか確認する方法がよく分からない状況です。
また、「Openメソッド」「Openステートメント」などで検索して調べましたが、ACCESSのテーブルを読み込み、Excelに書き込むようなイメージだったのですが、Excelのみで「Open」を使うメソッドは存在するのでしょうか。
「csv.Output」の修正案をご教示いただければ幸いです。
よろしくお願いいたします。

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

PC:Windows11
ソフト:Microsoft365 Excel

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

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

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

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

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

sazi

2023/01/27 02:37 編集

「Openメソッドを使って出力する方法はできませんか?」 現状は、「ADODB.stream」を使用しているので、それを変更するという要望なのでしょうか? ですが、そもそもどのような理由による変更要望なのでしょうか?
koburon

2023/01/27 08:25

>sazi様 >hatena19様 コメントありがとうございます。 「Openステートメント」に変更する理由について、レビュー担当者に確認したところ、 「t_社員マスタ」テーブルに入る項目は全て文字コードがShift-JISのみなので、CSVファイルを読み込む方法として「Openステートメント」を使用した関数を使った方が汎用性があり、今後、別のマクロを作成するときに参考になって役立つから、とのことでした。 「Openステートメント」と「ADODB.Stream」の違いについて調べて下記URLを見つけたので確認したところ、 https://nyanblog2222.com/office/2291/#toc5ADODB.Stream」を使用する方法はUTF-8、Shift-JISを含む各種文字コードに対応しているようですが、この認識で間違いないでしょうか。
odataiki

2023/01/27 09:39

ADODB.Stream」を使用する方法はUTF-8、Shift-JISを含む各種文字コードに対応していますね。 私個人はADODB.Streamの方が汎用性があると感じてますが、 環境や社内文化が異なるので、それに従う方がいいのではないでしょうか。
koburon

2023/01/30 01:24

>odataiki様 コメントありがとうございます。 企業よって「こうした方がいい」という独自の文化やルールがあるということですね。 社内でよく打合せして相談してからそれに従って作成しようと思います。
guest

回答1

0

ベストアンサー

open関数を使用した例です。
下記を参考しています。
参考URL
出力開始列=1 出力終了位置=7 にしています。変える場合は
Const stCol = 1
Const enCol = 7
の値を変えてください。
出力するファイル名は
csvFile = "d:\goo\data8\sample.csv"
と固定にしています。あなたの環境に合わせて適切に設定してください。
両端をダブルクオートでくくって出力します。

VBA

1Public Sub CSV出力() 2 Dim ws As Worksheet 3 Dim maxrow As Long 4 Dim csvFile As String 5 Dim fileNo As Integer 6 Dim wrow As Long 7 Dim wcol As Long 8 Dim i As Long 9 Dim val As String 10 Dim out_line As String 11 Const stCol = 1 12 Const enCol = 7 13 Dim arrVal(enCol - stCol) As String 14 15 csvFile = "d:\goo\data8\sample.csv" 16 Set ws = ActiveSheet 17 maxrow = ws.Cells(Rows.Count, 1).End(xlUp).Row 18 fileNo = FreeFile 19 Open csvFile For Output As #fileNo 20 For wrow = 3 To maxrow 21 i = 0 22 For wcol = stCol To enCol 23 '1データ取得 24 val = ws.Cells(wrow, wcol).Value 25 'データをダブルクオートでくくり、配列へ格納 26 arrVal(i) = wrap_data(val) 27 i = i + 1 28 Next 29 'カンマで連結 30 out_line = Join(arrVal, ",") 31 Print #fileNo, out_line 32 Next 33 Close #fileNo 34 MsgBox ("CSVファイルを「Shft_JIS」で出力しました。レコード部分のみ出力しています。") 35End Sub 36 37'入力文字列をダブルクオートでくくる 38Private Function wrap_data(ByVal val As String) As String 39 wrap_data = """" & val & """" 40End Function 41 42``` 

投稿2023/01/29 02:34

tatsu99

総合スコア5493

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

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

koburon

2023/01/30 01:19

回答ありがとうございます。 いただいたコードを元に、ファイルの出力先と表の列数を変更して試したところ、問題なく動作し、目的通りのCSVファイルを作成できました。 ベストアンサーとさせていただきます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.39%

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

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

質問する

関連した質問