#はじめに
VBScriptでSQL Serverに接続しSELECTした後にデータをExcelに出力する方法を調べたのでメモします。
コードや記載にコメントが少ないですが備忘録のような記事です。申し訳ございません。
落ち着いたらコメントを追記していきます。
#SQLServerにテスト用DBおよびテーブル、データを登録
--DB作成
CREATE DATABASE dbTest;
--Table作成
use dbTest;
CREATE TABLE [dbo].[Employee](
[No] [int] NOT NULL,
[Name] [nchar](15) NOT NULL,
[RegDate] [date] NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[No] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
--作成したTableに100万件テストデータを登録
DECLARE @p_InsertNumber Bigint -- INSERTする行数
SELECT @p_InsertNumber=1000000; -- 100万に設定
WITH Base AS
(
SELECT
1 AS n
UNION ALL
SELECT
n + 1
FROM
Base
WHERE
n < @p_InsertNumber
),
Nums AS
(
SELECT
Row_Number() OVER(ORDER BY n) AS n
FROM
Base
)
INSERT INTO Employee
SELECT
n
, 'test'
, GETDATE()
FROM
Nums
WHERE
n <= @p_InsertNumber
OPTION (MaxRecursion 0); -- 再帰クエリの再帰回数の上限をなくす
#VBScriptでSQL Serverに接続しSELECTした後にデータをExcelに出力
Option Explicit
'データベース接続情報を定義(Windows認証)
Const MYPROVIDERE = "Provider=SQLOLEDB;"
Const MYSERVER = "Data Source=DESKTOP-TEST\SQLEXPRESS;" 'サーバー
Const MYNINSYO = "Trusted_connection=yes;" 'Windows認証の場合
Const MYDATABASE = "Initial Catalog=dbTest;" '接続するデータベース名
Dim cn
Dim rs
Dim workbook
Dim excelObj
Dim worksheet
on error resume next
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
Set excelObj = CreateObject("Excel.Application")
if Err.Number = 0 Then
'データベース接続
cn.ConnectionString = MYPROVIDERE & MYSERVER & MYNINSYO & MYDATABASE
cn.Open
rs.ActiveConnection = cn
If Err.Number = 0 Then
'Excelの機能を利用するために必要
'Excelを非表示
excelObj.Visible = False
'Excelブックを新規作成
Set workbook = excelObj.Workbooks.Add()
Call SelectTable("Select * from Employee where No < 100;",1, "テスト1")
Call SelectTable("Select * from Employee1 where No < 10;",2, "テスト2")
Call SelectTable("Select * from Employee where No < 5;",3, "テスト3")
If Err.Number <> 0 Then
Wscript.Echo Err.Description
Else
'名前つけて保存
workbook.SaveAs("C:\Users\Desktop\test.xlsx")
'ワークブックを閉じる
workbook.Close
End If
Set workbook=Nothing
Else
Wscript.Echo Err.Description
End If
end if
'Excelを閉じる
worksheet.Close
excelObj.Quit
Set excelObj = Nothing
'データベース切断
rs.Close
cn.Close
On Error Goto 0
Wscript.Echo "処理終了"
'データベース接続しSelect実行
Sub SelectTable(sql,cnt, name)
'Select実行
rs.Source = sql
rs.Open
Call ExcelWrite(cnt, name)
rs.Close
End Sub
'データをExcelに出力
Sub ExcelWrite(cnt, name)
Dim i
Dim j
'シートを指定(名前Or番号で指定)
Set worksheet = workbook.Sheets(cnt)
worksheet.Name = name
i = 1
Do Until rs.EOF
For j = 0 To rs.Fields.Count - 1
If i = 1 Then
worksheet.Cells(i, j + 1) = rs.Fields(j).Name
End If
worksheet.Cells(i + 1, j + 1) = rs(j).Value
Next
rs.MoveNext
i = i + 1
Loop
End Sub
Excel出力で例外が発生した場合、Excelのタスクが残ってしまうというところがまだ解決していません。。
#Excel VBAでSQL Serverに接続しSELECTした後にデータをExcelに出力
いろいろ検討した結果、Excel VBAでSQL Serverに接続しSELECTした後にデータをシートに出力した方が簡潔ということになりました。
以下にサンプルを載せます。
Option Explicit
' SQL ServerにSELECT文を発行し、レコードセットへ取得し、Excelに書き出す。
Sub SQL_GetRecordSet()
On Error GoTo ErrorProc
Application.ScreenUpdating = False
Dim DBSrv As String
Dim DBName As String
Dim strSQL As String
Dim strConn As String
Dim strSheetName As String
'----------------------------------------------------
' DBSrvにDBサーバ名、DBNameにデータベース名
'----------------------------------------------------
DBSrv = "DESKTOP\SQLEXPRESS"
'DBSrv = "DBSERVER\SQLEXPRESS,49391" 'ポート指定付
DBName = "dbTest"
'----------------------------------------------------
' 発効するSQLの作成(レコードセットへ取り込むSELECT文)
'----------------------------------------------------
strSQL = "SELECT * FROM Employee(NOLOCK)"
'----------------------------------------------------
' 接続文字列の指定
'----------------------------------------------------
'Windows認証
strConn = "Provider=SQLOLEDB;Data Source='" & DBSrv & "';Initial Catalog='" & DBName & "';Trusted_Connection=Yes"
'SQL Server認証
'strConn = "Provider=SQLOLEDB;Data Source='" & DBSrv & "';Initial Catalog='" & DBName & "';UID=【ユーザ名】;PWD=【パスワード】;"
'書き込み先のシート作成
Worksheets.Add after:=Worksheets(Worksheets.Count)
strSheetName = Format(Now, "yyyy年MM月dd日hh時mm分ss秒")
ActiveSheet.Name = strSheetName
Worksheets(strSheetName).Cells.NumberFormatLocal = "@"
'Excelに書き出し
Call WriteExcel(strConn, strSQL, strSheetName)
MsgBox "正常に書き出し完了"
Exit Sub
'エラー処理
ErrorProc:
MsgBox Err.Number & vbCrLf & Err.Description
End Sub
Sub WriteExcel(strConn As String, strSQL As String, strSheetName As String)
Dim i As Long
Dim j As Long
Dim rs As Recordset
'オブジェクト生成
Set rs = New ADODB.Recordset
'SQLを実行し、読み取り専用でレコードセットへ取得
rs.Open strSQL, strConn, adOpenForwardOnly, adLockReadOnly, adCmdText
'レコードセットへ先頭へ
rs.MoveFirst
'Excelに書き出し
i = 1
Do Until rs.EOF
For j = 0 To rs.Fields.Count - 1
If i = 1 Then
Worksheets(strSheetName).Cells(i, j + 1) = rs.Fields(j).Name
End If
If IsNull(rs(j).Value) Then
Worksheets(strSheetName).Cells(i + 1, j + 1) = "NULL"
Else
Worksheets(strSheetName).Cells(i + 1, j + 1) = rs(j).Value
End If
Next
rs.MoveNext
i = i + 1
Loop
'クローズ
rs.Close
Set rs = Nothing
End Sub
###参考にしたサイト
http://itdiary.info/microsoft-office/post-1355/