WindowsバッチファイルでCSVを読み込む

2017年5月23日

forのオプションであるtokensを使ってCSVを読み込むサンプルは検索するとたくさん出てくるけれど,tokens=1,2,…だとASCII文字(A-Z,a-z)の数だけしか列データを読み込めない.

なので,たくさん列データを読めるようなバッチを書いた.
(ついでに先頭行はヘッダとして読むことに)

@echo off
setlocal enabledelayedexpansion

set CSVFILE=%~dp0test.csv

rem ===========================
rem  Load CSV file
rem ===========================
:load_csv
set COL_INDEX=
set CSVTITLE=
set CSVDATA=

set IS_TITLE=TRUE
set ROWNUM=0
for /f "eol=# delims=" %%A in (%CSVFILE%) do (
  rem echo call :read_csv_line "%%A"
  call :read_csv_line "%%A"
  set COLSIZE=!COLNUM!
  for /l %%n in (0,1,!COLSIZE!) do (
    if defined IS_TITLE (
      set TMP=!CSVLINE[%%n]!
      set CSVTITLE[%%n]=!TMP!
      set COL_INDEX[!TMP!]=%%n
    ) else (
      set CSVDATA[!ROWNUM!][%%n]=!CSVLINE[%%n]!
    )
  )
  if defined IS_TITLE set IS_TITLE=
  set /a ROWNUM+=1
)
set /a ROWSIZE=!ROWNUM!-1
set /a COLSIZE=!COLNUM!

rem ===========================
rem  Display CSV data
rem ===========================

echo CSV Data Size [%ROWSIZE% x %COLSIZE%]
echo.

for /l %%r in (1,1,!ROWSIZE!) do (
  for /l %%c in (0,1,!COLSIZE!) do (
    set TITLE=!CSVTITLE[%%c]!
    set DATA=!CSVDATA[%%r][%%c]!
    echo Data %%r: !TITLE! = !DATA!
  )
)

goto end

rem ===========================
rem  Read CSV line
rem ===========================
:read_csv_line
  set LINE=%1
  rem echo call :read_csv_inner 0 %LINE%
  call :read_csv_inner 0 %LINE%
  goto :EOF

:read_csv_inner
  set NUM=%1
  set LINE=%2
  for /f "delims=, tokens=1,*" %%A in (!LINE!) do (
    set DATA=%%A
    set REST="%%B"
    set CSVLINE[!NUM!]=!DATA!
    rem echo ROW: !ROWNUM! COL: !NUM! DATA: !DATA! REST: !REST!
    if not !REST!=="" (
      set /a NUM+=1
      call :read_csv_inner !NUM! !REST!
    )
  )
  set COLNUM=!NUM!
  goto :EOF

:end
pause
endlocal

rem Copyright (c) 2016 @tanitanin
rem This software is released under the MIT License.
rem http://opensource.org/licenses/mit-license.php