Access VBA 法人番号のCSVをインポートするときのフローと注意点

##お断り
英語などは600という幅を持っていますが、あくまでも番号を確認するためなので、そうした長いものは切ります。このためエラーが出ます。
今回はCSVファイル、accdbファイルは`%USERPROFILE%\Documents\`を前提としています。当然のことながら、正確性については保証しておりません。


#それではサイトに行きましょう
https://www.houjin-bangou.nta.go.jp/download/
全件データのダウンロード（各都道府県別）
##CSV形式SHIFT-JIS版をダウンロード
***CSV形式・Shift-JIS***
***CSV形式・Unicode***
XML形式・Unicode

愛媛県  zip 2MB
高知県  zip 853KB
愛媛県  zip 2MB
高知県  zip 909kB
 
容量がすくない高知県を使いますが、CSVはShift-JISもUNICODE(中身はUTF-8)もダウンロードするときファイル名が同じなのでクリックする位置を間違うと違うコードのファイルをダウンロードします。また後で述べるようにUNICODEのためにはまずSHIFT-JISで変換が可能になるテーブルとインポート定義を作成したほうがよいので、SHIFT-JISをダウンロードします。
なお、今回はxmlは使いません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/1691128f-14fe-04c4-faa3-73d6ccac32ed.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/e4b953cb-5cd8-eb81-e195-0708fc5d4948.png)


ここでいちど
https://www.houjin-bangou.nta.go.jp/download/
ここに戻って、仕様の資料を入手します。
ダウンロードファイルのデータ定義（データの項目名等について）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/f26961a7-350d-6f71-ec78-07497bcb3459.png)
Excelの方が項目をコピペできるので、そちらをダウンロードしましょう。

<UL>
<li>Web-API（Ver.4.0）の追加
<li>ダウンロードファイル及びWeb-API（Ver.4.0）のデータ項目に検索対象除外の情報を追加（項番36）。
</UL>
現在項番は36まであります。
問題はこの項番36がエラーを起こしていると考えられることです。
#月次データの項目は7番から
##Excelでそのままとるとこうなるので要注意
###注意点はダブりがあるのと、そもそも予約語があってエラーが起きる
注意点はダブりがあるのと、英語だと予約語があり、Accessのフィールド名にするとエラーが起きる点です
sequenceNumber
corporateNumber
process
process
correct
updateDate
changeDate
***name***:arrow_left:予約語のためエラーになる
nameImageId
***kind***
***kind***:arrow_left:単純に項目名を取ると重複かつ予約語でエラーになる
prefectureName
cityName
streetNumber
addressImageId
prefectureCode
cityCode
postCode
addressOutside
***"addressOutside
ImageId"***:arrow_left:項目名をテキストでコピーしてダブルクォーテーションが入るのは改行が入っている
closeDate
closeCause 
successor
CorporateNumber"
changeCause
assignmentDate
latest
enName
enPrefectureName
enCityName
enAddressOutside
furigana
hihyoji
##この項目は英語ではなく日本語にした方がよい
この国際化の時代に恐縮ですが。。。
英語は予約語を使用しているため、エラーになります。
ダブり、空白は日本語でもでますが、消します。""で囲まれているのは2行になっていますが消しましょう

一連番号
法人番号
処理区分
訂正区分
更新年月日
変更年月日
商号又は名称
商号又は名称イメージID
法人種別
国内所在地（都道府県）
国内所在地（市区町村）
国内所在地（丁目番地等）
国内所在地イメージID
都道府県コード
市区町村コード
郵便番号
国外所在地
国外所在地イメージID
登記記録の閉鎖等年月日
登記記録の閉鎖等の事由
承継先法人番号
変更事由の詳細
法人番号指定年月日
最新履歴
商号又は名称（英語表記）
国内所在地（都道府県）(英語表記）
国内所在地（市区町村丁目番地等）（英語表記）
国外所在地（英語表記）
フリガナ
検索対象除外<- ところで上記と比較すると、hihyoujiって英語だったんですね。知らんかったわー。

##Create TableのSQLを作る
CREATE TABLE ステートメント (Microsoft Access SQL)
https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/create-table-statement-microsoft-access-sql

```vb
Sub CreateTableX2() 
 
Dim dbs As Database 
' Modify this line to include the path to Northwind 
' on your computer. 
Set dbs = OpenDatabase("Northwind.mdb") 
 
' Create a table with three fields and a unique 
' index made up of all three fields. 
dbs.Execute "CREATE TABLE MyTable " _ 
& "(FirstName CHAR, LastName CHAR, " _ 
& "DateOfBirth DATETIME, " _ 
& "CONSTRAINT MyTableConstraint UNIQUE " _ 
& "(FirstName, LastName, DateOfBirth));" 
dbs.Close 
End Sub
```

Sampleの特にSQLの中身を中身を作ります。しかし国内所在地の丁番地は300字、英語は500字とかありますが、Accessは255字までしかありません。このため、法人番号簿のCreate TABLEにおいて、基本的に字数を255に設定しているところは255文字を超えていますので、本当はメモ型にすべきです。そうしていないため、必ず取り込めないケースが発生します。しかし、データベースが大きくなり全体が取り込めなくなる恐れがあるため、この欠点は放置します。
　番号をまとめて検索するのが目的であって完全な名簿が欲しいわけではないし、また、それならCSVから読めばいいわけです。
また、一連番号はいいのですが、コードや法人番号はすぐ表示が整数ではなく指数表示になってしまいがちなので、基本的にテキストで取り込みます。


一連番号 LONG, 法人番号 Text(13), [処理区分] Text(2), [訂正区分] TINYINT, 更新年月日 DateTime, [変更年月日], DateTime, [商号又は名称] Text(255),商号又は名称イメージID Text(8), [法人種別] Text(3), [国内所在地(都道府県)] Text(10),[国内所在地(市区町村)] Text(20). [国内所在地(丁目番地等)] Text(255), [国内所在地イメージID] Text(8),[都道府県コード] Text(2), [市区町村コード] Text(3), [郵便番号] Text(7), [国外所在地] Text(255),[国外所在地イメージID] Text(8), [登記記録の閉鎖等年月日] Datatime, [登記記録の閉鎖等の事由] Text(255), [承継先法人番号] Text(13),[変更事由の詳細] Text(255). [法人番号指定年月日] Datetime,[最新履歴] TinyInt, [商号又は名称(英語表記)] Text(255), [国内所在地(都道府県)(英語表記)] Text(9), [国内所在地(市区町村以下(英語表記)] Text(255),[国外所在地(英語表記)]  Text(255),[フリガナ] Text(255),[検索対象除外] byte

 - かっこを半角に置換して

Create Table 39_kochi_all_20200331(一連番号 LONG, 法人番号 Text(13), [処理区分] Text(2), [訂正区分] TINYINT, 更新年月日 DateTime, [変更年月日], DateTime, [商号又は名称] Text(255),商号又は名称イメージID Text(8), [法人種別] Text(3), [国内所在地(都道府県)] Text(10),[国内所在地(市区町村)] Text(20). [国内所在地(丁目番地等)] Text(255), [国内所在地イメージID] Text(8),[都道府県コード] Text(2), [市区町村コード] Text(3), [郵便番号] Text(7), [国外所在地] Text(255),[国外所在地イメージID] Text(8), [登記記録の閉鎖等年月日] Datatime, [登記記録の閉鎖等の事由] Text(255), [承継先法人番号] Text(13),[変更事由の詳細] Text(255). [法人番号指定年月日] Datetime,[最新履歴] TinyInt, [商号又は名称(英語表記)] Text(255), [国内所在地(都道府県)(英語表記)] Text(9), [国内所在地(市区町村以下(英語表記)] Text(255),[国外所在地(英語表記)]  Text(255),[フリガナ] Text(255),[検索対象除外] byte);

最後に`Create Table 39_kochi_all_20200331(`と`);`をくっつけますがSQLをチェックするため、クエリデザインでSQLの画面にして貼り付けます。

```sql
Create Table 39_kochi_all_20200331(一連番号 LONG, 法人番号 Text(13), [処理区分] Text(2), [訂正区分] TINYINT, 更新年月日 DateTime, [変更年月日], DateTime, [商号又は名称] Text(255),商号又は名称イメージID Text(8), [法人種別] Text(3), [国内所在地(都道府県)] Text(10),[国内所在地(市区町村)] Text(20). [国内所在地(丁目番地等)] Text(255), [国内所在地イメージID] Text(8),[都道府県コード] Text(2), [市区町村コード] Text(3), [郵便番号] Text(7), [国外所在地] Text(255),[国外所在地イメージID] Text(8), [登記記録の閉鎖等年月日] Datatime, [登記記録の閉鎖等の事由] Text(255), [承継先法人番号] Text(13),[変更事由の詳細] Text(255). [法人番号指定年月日] Datetime,[最新履歴] TinyInt, [商号又は名称(英語表記)] Text(255), [国内所在地(都道府県)(英語表記)] Text(9), [国内所在地(市区町村以下(英語表記)] Text(255),[国外所在地(英語表記)]  Text(255),[フリガナ] Text(255),[検索対象除外] byte);
```

まずCreteTableをチェックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/2e41f49f-37bf-497b-d04c-7fdda8aa1361.png)

これで実行をクリックすると、ミスがある周辺で止まるという機能があります。
この機能を使って、どこで止まるかを見ながら修正します。ちょっと見づらいうえに、どういう点でエラーになるのか知らないとこれで編集するのは難しいですね。

```sql
Create Table 39_kochi_all_20200331 ([一連番号] LONG, [法人番号] Text(13), [処理区分] Text(2), [訂正区分] byte, [更新年月日] DateTime, [変更年月日] DateTime, [商号又は名称] Text(255), [商号又は名称イメージID] Text(8), [法人種別] Text(3), [国内所在地(都道府県)] Text(10), [国内所在地(市区町村)] Text(20), [国内所在地(丁目番地等)] Text(255), [国内所在地イメージID] Text(8),[都道府県コード] Text(2), [市区町村コード] Text(3), [郵便番号] Text(7), [国外所在地] Text(255), [国外所在地イメージID] Text(8), [登記記録の閉鎖等年月日] Datetime, [登記記録の閉鎖等の事由] Text(255), [承継先法人番号] Text(13), [変更事由の詳細] Text(255), [法人番号指定年月日] Datetime, [最新履歴] Byte, [商号又は名称(英語表記)] Text(255), [国内所在地(都道府県)(英語表記)] Text(9), [国内所在地(市区町村以下(英語表記)] Text(255),[国外所在地(英語表記)]  Text(255),[フリガナ] Text(255),[検索対象除外] byte);
```

今回間違っていたのは

 - 実際は全角のスペースだった
 - 実際はテーブル名とかっこの間に半角スペースが必要だった `20200331 ([一連番号]`
 - 半角が二つ続くとエラー、TinyIntはつかないというエラーがありました。
 - 角かっこは付けるときは全てのフィールド名につけた方がいいようです。
 - また、コンマと角かっこをくっつけるとエラーになりました。 `,[法人番号]` OK `, [法人番号]`

これが動くようになると出来上がりです。

```vb
Sub CreatePrefectureTable()
 'For Access
Dim dbs As Database
Set dbs = CurrentDb '書き換え
Dim sSQL As String '追加
sSQL = "Create Table 39_kochi_all_20200331 ([一連番号] LONG, [法人番号] Text(13), [処理区分] Text(2), [訂正区分] byte, [更新年月日] DateTime, [変更年月日] DateTime, [商号又は名称] Text(255), [商号又は名称イメージID] Text(8), [法人種別] Text(3), [国内所在地(都道府県)] Text(10), [国内所在地(市区町村)] Text(20), [国内所在地(丁目番地等)] Text(255), [国内所在地イメージID] Text(8),[都道府県コード] Text(2), [市区町村コード] Text(3), [郵便番号] Text(7), [国外所在地] Text(255), [国外所在地イメージID] Text(8), [登記記録の閉鎖等年月日] Datetime, [登記記録の閉鎖等の事由] Text(255), [承継先法人番号] Text(13), [変更事由の詳細] Text(255), [法人番号指定年月日] Datetime, [最新履歴] Byte, [商号又は名称(英語表記)] Text(255), [国内所在地(都道府県)(英語表記)] Text(9), [国内所在地(市区町村以下(英語表記)] Text(255),[国外所在地(英語表記)]  Text(255),[フリガナ] Text(255),[検索対象除外] byte);"
dbs.Execute sSQL
Application.RefreshDatabaseWindow 'ADD
End Sub

```

こうしてクエリからでもVBAからでもテーブルが作成できるようにしておきます。
作ったテーブルにテキストデータを入れてみます。
こういうのが全く分からないときは、リンクテーブルを作り、その時フィールドの名前を決めます。また、設定から保存します。
これはShift-Jisの時のインポートで使えます。
 
日付に0を表示にチェックをいれてください。
ここで保存を押すとざっくりチェックしてくれます。
CSV_ShiftJIs_ImportDefinition
この場合、正確に定義しているため、最後までスムーズにいきます。
変更理由がいくつか切り捨てられましたが、以下のように数件しかエラーが出ません。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/6d9644d5-6911-c2be-0d12-56c2db47fb86.png)


大体成功です。
次は選択クエリを作ります。
裁判所を検索してみましょう。
 
```sql
SELECT [39_kochi_all_20200331].[一連番号], [39_kochi_all_20200331].[法人番号], [39_kochi_all_20200331].[商号又は名称], [39_kochi_all_20200331].[国内所在地(市区町村)] FROM 39_kochi_all_20200331 WHERE ((([39_kochi_all_20200331].[商号又は名称]) Like "*裁判所*"));
```

ちなみに開業しているところはスペースでも代用できます。
 
それでは必要な法人番号が得られたので、それ以外を削除します。
デザインから削除に変えてNot Likeにします。


```sql
DELETE [39_kochi_all_20200331].[一連番号], [39_kochi_all_20200331].[法人番号], [39_kochi_all_20200331].[商号又は名称], [39_kochi_all_20200331].[国内所在地(市区町村)] FROM 39_kochi_all_20200331 WHERE ((([39_kochi_all_20200331].[商号又は名称]) Not Like "*裁判所*"));
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/36a95cc9-82ef-34ba-4672-ee1fc846f95d.png)

##次のユニコードが難しい
39_kochi_all_20200331.zipやできたフォルダ、CSVを削ります。
また裁判所だけになったテーブルは39_Koutiに変えます。
39_kochi_all_20200331_インポート エラーも削除します。
Q_MakePrefTableまたはVBAでテーブルを作ります。
再びインポートを行います。ユニコードはUTF-8のようです。ファイル名は同じでも文字コードが違います。
このため、文字化けが起きます。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/6acdf0cd-932c-346c-fec2-f37f75e1ce19.png)

 

そしてShiftJisの定義を使うためいったん文字コードをUTF-8にしてOKを押してください。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/675861d6-a7a4-6314-da3d-6db65aae17d8.png)

そしてこの状態から再び、設定をクリックして
定義をクリックし、先ほどの定義を選択します。
 
 


ここで定義の文字コードをUTF-8に変えて保存します。
CSV_UTF8_ImportDefinition
といいたいところですが、これでは大量の読み込みエラーが発生します。
そこで手動でField30をフリガナの下に追加し、「スキップ」をチェックし、そのうえで
CSV_UTF8_ImportDefinition
として保存してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/60f06a08-9a35-8ef1-1f6b-8c4f8fad47f7.png)

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/049d54c0-ff1d-b85c-2c95-458883672d49.png)


高知県はほぼ全レコードがエラーという表示になりますが、2MBクラスの場合はField30が読み込めないためこのインポートウィザードは途中で止まってしまいます。このためShiftJisを使って支障がない場合は、そちらを使った方がよいです。

また、この流れがわからないときは、xlsx形式にしてヘッダー行を書き込み、保存してインポートしてもよいです。
東京は無理っぽいですが。

#なぜ、Accessを使うのか。
これやってみたらわかりますが、Accessで検索する方が断然早いのです。とくに5MBを超えるとExcelはパフォーマンスが落ちます。
このため、この取り込む時間以上に広く大量に法人番号がいるときには欠かせないテクニックです。これならAPIを申請する必要もないですし、ネットが遅くてイライラすることもありません。