Excelの文字列結合で作ったりするinsert文とかを簡単に作るスクリプト

よくExcel表のデータから文字列結合でinsert文を作ったりするが、それを簡単に作るスクリプト

erbを使用。templateファイルの中でif文や正規表現も使えるので便利。


each_line.rb

# -*- coding: utf-8 -*-
require 'erb'
require 'fileutils'

Encoding.default_external = "UTF-8"  # windows環境で入力およびtemplateファイルがUTF-8の場合
RESULT_DIR = "./result"

FileUtils.mkdir(RESULT_DIR) unless FileTest.exist?(RESULT_DIR)
@lines = []
File.foreach(ARGV[0]) do |line|
  @lines << line.chomp.split(/\t/) unless line.chomp.empty?
end

template_file_name = ARGV[1]
template_extension = template_file_name.gsub(/.*\.(.*)/, '\1')
template = File.open(ARGV[1]) { |f| f.read }  
result = ERB.new(template, nil, "-").result(binding)  
File.open("#{RESULT_DIR}/#{Time.now.strftime("%Y%m%d_%H%M%S")}.#{template_extension}", 'w') {|f| f.puts result}

使用例1

input1.txt

00001	山田太郎
00002	田中花子

template1.sql

<%- @lines.each do |l| -%>
insert into emp (no_emp, nm_emp) values ('<%= l[0] %>', '<%= l[1] %>')
/
<%- end -%>
commit
/
ruby each_line.rb input1.txt template1.sql

作成されるファイル

insert into emp (no_emp, nm_emp) values ('00001', '山田太郎')
/
insert into emp (no_emp, nm_emp) values ('00002', '田中花子')
/
commit
/

使用例2

これはExcelでは相当書かないとできまい。


input2.txt

2012/05/05
2012/05/12
2012/05/19

template2.sql

select
	dept_no
<%- @lines.each_with_index do |l, i| -%>
	, T<%= i %>.cnt as CNT_<%= l[0].gsub("/", "") %>
<%- end -%>
from dept
<%- @lines.each_with_index do |l, i| -%>
left outer join (
	select no_dept, count(*) as cnt
	from emp
	group by no_dept
	where trunc(insert_date) <= to_date('<%= l[0] %>', 'yyyy/mm/dd')
) T<%= i %>
on dept.no_dept = T<%= i %>.no_dept
<%- end -%>
/
ruby each_line.rb input2.txt template2.sql

作成されるファイル

select
	dept_no
	, T0.cnt as CNT_20120505
	, T1.cnt as CNT_20120512
	, T2.cnt as CNT_20120519
from dept
left outer join (
	select no_dept, count(*) as cnt
	from emp
	group by no_dept
	where trunc(insert_date) <= to_date('2012/05/05', 'yyyy/mm/dd')
) T0
on dept.no_dept = T0.no_dept
left outer join (
	select no_dept, count(*) as cnt
	from emp
	group by no_dept
	where trunc(insert_date) <= to_date('2012/05/12', 'yyyy/mm/dd')
) T1
on dept.no_dept = T1.no_dept
left outer join (
	select no_dept, count(*) as cnt
	from emp
	group by no_dept
	where trunc(insert_date) <= to_date('2012/05/19', 'yyyy/mm/dd')
) T2
on dept.no_dept = T2.no_dept
/