Excelファイルを読みデータベースに登録
Excelファイルを読み、データベースに登録するサンプルです。
ExcelCreatorを利用し、Excelファイルを読み、OracleのEMP表にインポートします。
(シチュエーション)
複数の人がインポートするExcelファイルを持っています。
で、人によって列位置や列のタイトルを自分がわかりやすくしたいとの事です。例えばAさんのExcelファイルはEMP表の「EMPNO」がC列、BさんはD列、またタイトルも[EMPNO]や[EMP NUMBER]だったりします。
インポートする行を設定可能にし、インポートした行にはフラグを立てます。
これらの要件を考慮したサンプルを作成します。
インポートするExcelファイル
人によって、列位置や列タイトルが違うとの事なので、この項目はセルA3を見る..等、固定できません。
なので、かっこ悪いけどちょっとしたルール設定をユーザにお願い。
- 列項目を特定する為の文字列や数値をにタイトルの上につけてもらう。(例 「3」はDEPTNO等、ルールを決めておく)(A列のどこか)
- データ行開始位置を特定できる文字列や数値を、セル(固定セル)につけてもらう。(A列のどこか)
- データ行のどこかの列(例えば下図の「インポートする」列)が一定数連続して空白セルなら終了(もちろん空白の行は処理しない)
などなど、めんどくさくない程度にルール設定をさせてもらえれば、どうにでもなるでしょう。
AさんのExcelファイル
B3 - K3 に列を表す番号を入れてもらいます。
4行目は、列のタイトルですね。そしてセルA5には「DATA」と入れてもらい、その行からデータが始まるものとします。

BさんのExcelファイル
B4 - K4 に列を表す番号を入れています。Aさんは3行目でした。
また、列位置もAさんとは異なってます。
5行目は、列のタイトルです。

サンプルプログラム
Imports Oracle.DataAccess.Client
Public Class frmXlsCreator2_Import
Private ConnectionString As String
Private dt As DataTable = Nothing
'列位置保管用
Structure ColumnFieldIdx
Dim isImport As Integer
Dim ImportFlg As Integer
Dim EMPNO As Integer
Dim ENAME As Integer
Dim JOB As Integer
Dim MGR As Integer
Dim HIREDATE As Integer
Dim SAL As Integer
Dim COMM As Integer
Dim DEPTNO As Integer
End Structure
Private ColumnIndex As ColumnFieldIdx
Private Sub frmXlsCrearor2_Import_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'接続文字列のセット
ConnectionString = "DATA SOURCE=ORCL;User ID=scott;password=tiger;"
Edit1.Text = My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\vbnetdb_ExcelCreatorSample.xls"
getSheetList()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
getSheetList()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ExcelImport(Edit1.Text, Combo1.SelectedItem.Content.ToString)
End Sub
'''
''' シート名を取得してコンボボックスにセット
'''
'''
Private Sub getSheetList()
Dim i As Integer
XlsCr1.OpenBook(Edit1.Text, "")
Combo1.Items.Clear()
For i = 0 To XlsCr1.SheetCount - 1
Combo1.Items.Add(XlsCr1.SheetName2(i))
Next
XlsCr1.CloseBook(False)
End Sub
'''
''' Excel Creator エラーイベント
'''
'''
'''
'''
Private Sub XlsCreator1_Error(ByVal sender As Object, ByVal e As ExcelCreator.XlsCreatorEventArgs) Handles XlsCr1.Error
Throw New Exception(e.ErrorNo.ToString & ":" & XlsCr1.ErrorMessage)
End Sub
'''
''' ExcelファイルからImport
'''
'''
'''
'''
Private Sub ExcelImport(ByVal SourceFileName As String, ByVal SheetName As String)
Dim col As Integer
Dim row As Integer
'連続空白セルカウンタ
Dim NullCount As Integer = 0
Try
'既存のExcelファイルを読み書きオープン
XlsCr1.OpenBook(SourceFileName, "")
'シートの切り替え:シート名からシートNoを取得して切り替え
XlsCr1.SheetNo = XlsCr1.SheetNo2(SheetName)
'----------------------------------------
'各列の列位置を取得
'----------------------------------------
'列位置格納用変数の初期化
With ColumnIndex
.isImport = -1
.ImportFlg = -1
.EMPNO = -1
.ENAME = -1
.JOB = -1
.MGR = -1
.HIREDATE = -1
.SAL = -1
.COMM = -1
.DEPTNO = -1
End With
'列番号がセットされているセルの行位置、データ開始行の行位置を取得
'列番号が設置されているセルの行位置は、A列で「HEAD」と記してもらう
'データ開始行のセル行位置はA列で「DATA」と記してもらう
Dim isEnd As Boolean = False
Dim HeadNoRow As Integer = -1
Dim HeadNoCol As Integer = 0
Dim DataNoRow As Integer = -1
row = 0
While Not isEnd
If XlsCr1.Pos(0, row).Str.ToUpper = "HEAD" Then
HeadNoRow = row
NullCount = 0
ElseIf XlsCr1.Pos(0, row).Str.ToUpper = "DATA" Then
DataNoRow = row
NullCount = 0
Else
NullCount += 1
End If
If HeadNoRow > -1 And DataNoRow > -1 Then
isEnd = True
Else
row += 1
If NullCount > 9 Then
MessageBox.Show("列番号文字列(HEAD)、データ開始行文字列(DATA)が見つかりません..", _
"インポートを終了します", MessageBoxButtons.OK, MessageBoxIcon.Information)
XlsCr1.CloseBook(False)
Exit Try
End If
End If
End While
Dim MaxData As Size = XlsCr1.MaxData(ExcelCreator.xlPoint.ptMaxPoint)
isEnd = False
col = HeadNoCol + 1
While Not isEnd
If XlsCr1.Pos(col, HeadNoRow).Str.Trim.Length > 0 Then
Select Case XlsCr1.Pos(col, HeadNoRow).Str.Trim
Case "1" : ColumnIndex.isImport = col
Case "2" : ColumnIndex.ImportFlg = col
Case "3" : ColumnIndex.EMPNO = col
Case "4" : ColumnIndex.ENAME = col
Case "5" : ColumnIndex.JOB = col
Case "6" : ColumnIndex.MGR = col
Case "7" : ColumnIndex.HIREDATE = col
Case "8" : ColumnIndex.SAL = col
Case "9" : ColumnIndex.COMM = col
Case "10" : ColumnIndex.DEPTNO = col
Case Else
End Select
col += 1
Else
isEnd = True
End If
End While
'----------------------------------------
'データ開始行
'----------------------------------------
isEnd = False
row = DataNoRow
While Not isEnd
'「インポートする」列に空白セルが10個続いたら終わる事にする
If XlsCr1.Pos(ColumnIndex.isImport, row).Str.Trim.Length > 0 Then
NullCount = 0
If XlsCr1.Pos(ColumnIndex.isImport, row).Str.Trim = "1" Then
'Oracle更新
ImportData( _
XlsCr1.Pos(ColumnIndex.EMPNO, row).Long, _
XlsCr1.Pos(ColumnIndex.ENAME, row).Str.TrimEnd, _
XlsCr1.Pos(ColumnIndex.JOB, row).Str.TrimEnd, _
XlsCr1.Pos(ColumnIndex.MGR, row).Long, _
DateTime.FromOADate(Convert.ToDouble(XlsCr1.Pos(ColumnIndex.HIREDATE, row).Value)), _
CDec(XlsCr1.Pos(ColumnIndex.SAL, row).Double), _
CDec(XlsCr1.Pos(ColumnIndex.COMM, row).Double), _
XlsCr1.Pos(ColumnIndex.DEPTNO, row).Long)
'インポート済みFLGセット
XlsCr1.Pos(ColumnIndex.ImportFlg, row).Long = 1
End If
Else
NullCount += 1
If NullCount > 9 Then
isEnd = True
End If
End If
row += 1
End While
'Excelファイル保存
XlsCr1.CloseBook(True)
'Gridに表示
ShowData()
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
XlsCr1.CloseBook(False)
Finally
End Try
End Sub
'''
''' EMP表データ登録・更新
'''
'''
'''
'''
'''
'''
'''
'''
'''
'''
Private Sub ImportData(ByVal EmpNo As Integer, ByVal EName As String, ByVal Job As String, _
ByVal Mgr As Integer, ByVal HireDate As Date, ByVal Sal As Decimal, _
ByVal Comm As Decimal, ByVal DeptNo As Integer)
Const cmdSelect As String = _
"select 'HOGE' from EMP " & _
"where " & _
"EMPNO = :EMPNO and " & _
"ROWNUM <= :WROWNUM"
Const cmdInsert As String = _
"insert into EMP (" & _
"EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO" & _
") values (" & _
":EMPNO, :ENAME, :JOB, :MGR, :HIREDATE, :SAL, :COMM, :DEPTNO" & _
")"
Const cmdUpdate As String = _
"update EMP set " & _
"ENAME = :ENAME, JOB = :JOB, MGR = :MGR, HIREDATE = :HIREDATE," & _
"SAL = :SAL, COMM = :COMM, DEPTNO = :DEPTNO " & _
"where " & _
"EMPNO = :EMPNO"
Dim isPresence As Boolean = False
Dim rd As OracleDataReader = Nothing
Try
Using cn As New OracleConnection(ConnectionString)
cn.Open()
Using cmd As New OracleCommand(cmdSelect, cn)
cmd.BindByName = True
cmd.Parameters.Add("EMPNO", OracleDbType.Int32).Value = EmpNo
cmd.Parameters.Add("WROWNUM", OracleDbType.Int32).Value = 1
rd = cmd.ExecuteReader
If rd.Read Then
isPresence = True
End If
rd.Close()
If Not isPresence Then
cmd.CommandText = cmdInsert
Else
cmd.CommandText = cmdUpdate
End If
cmd.Parameters.Clear()
cmd.Parameters.Add("EMPNO", OracleDbType.Int32).Value = EmpNo
cmd.Parameters.Add("ENAME", OracleDbType.Varchar2).Value = EName
cmd.Parameters.Add("JOB", OracleDbType.Varchar2).Value = Job
cmd.Parameters.Add("MGR", OracleDbType.Int32).Value = Mgr
cmd.Parameters.Add("HIREDATE", OracleDbType.Date).Value = HireDate
cmd.Parameters.Add("SAL", OracleDbType.Decimal).Value = Sal
cmd.Parameters.Add("COMM", OracleDbType.Decimal).Value = Comm
cmd.Parameters.Add("DEPTNO", OracleDbType.Int16).Value = DeptNo
cmd.ExecuteNonQuery()
End Using
cn.Clone()
End Using
Catch ex As Exception
Throw ex
Finally
If Not IsNothing(rd) Then
If Not rd.IsClosed Then
rd.Close()
End If
rd.Dispose()
End If
End Try
End Sub
'''
''' データ表示
'''
'''
Private Sub ShowData()
Const cmdSelect As String = _
"select " & _
"EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO " & _
"from EMP"
Try
Using da As New OracleDataAdapter(cmdSelect, ConnectionString)
dt = New DataTable
da.Fill(dt)
C1TrueDBGrid1.DataSource = dt
End Using
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
履歴
- 2011/08/30
- 公開