競馬成績表データベースを作る(ツール-Excel編)

1.概要

競馬成績表データベースを作るの第四弾です。これまで、作成したデータベースを活用するためには、検索表示などができないと 何の役にも立ちません。今回は、Excel VBAで作成します。当ブログ記事の「Excelでデータベース(SQLite3)を扱う」 で紹介しているテンプレートとなるソースコードを元にして、検索部分とデータ出力機能を追加しデータが抽出できるようにしたものです。 データベースをしっかり作成していれば、競馬以外の他の用途でも、いろいろと応用の効くものとすることができます。

2.ソースコード

まずは、簡単に操作方法を説明します。Yahoo競馬レース成績表検索.xlsmを起動します。 検索条件のコンボボックスで「競馬場」、「距離」、「コース」の3つの条件を選択して、実行ボタンをクリックします。 抽出対象データがあれば、100件/1ページ単位にデータが表示されます。ページ制御をしていますので、「次ページ」、 「前ページ」、「先頭」、「最終」のボタンをクリックしてページを表示させます。 また、「出力」ボタンをクリックすると、CSV形式で抽出したデータを外部出力できます。「消去」ボタンは、 画面上のデータを強制的に消去するものです。新たな条件で「実行」ボタンをクリックすれば、前処理として 消去(画面クリア)させていますので、通常は操作不要です。尚、Yahoo競馬レース成績表検索.xlsmの実行には、 SQLiteODBCとこのプログラムで利用するデータベース(pegasus.db)必要ですので事前に準備しておいて下さい。

ThisWorkbookは、ブックを開いた時の初期設定処理をしています。検索条件設定用のコンボボックスに値をセットします。

'***** ブックを開いた時の初期設定処理 *****
Private Sub Workbook_Open()
    
    Sheets("成績表").Select
    Worksheets("成績表").Activate

    '***** 検索条件用のコンボボックスを設定 *****
    ' 競馬場
    Dim CBRaceKaisai(10)
        CBRaceKaisai(0) = "東京"
        CBRaceKaisai(1) = "中山"
        CBRaceKaisai(2) = "京都"
        CBRaceKaisai(3) = "阪神"
        CBRaceKaisai(4) = "中京"
        CBRaceKaisai(5) = "札幌"
        CBRaceKaisai(6) = "函館"
        CBRaceKaisai(7) = "福島"
        CBRaceKaisai(8) = "新潟"
        CBRaceKaisai(9) = "小倉"
    ' 距離
    Dim CBKyori(20)
        CBKyori(0) = "1000"
        CBKyori(1) = "1150"
        CBKyori(2) = "1200"
        CBKyori(3) = "1300"
        CBKyori(4) = "1400"
        CBKyori(5) = "1500"
        CBKyori(6) = "1600"
        CBKyori(7) = "1700"
        CBKyori(8) = "1800"
        CBKyori(9) = "2000"
        CBKyori(10) = "2100"
        CBKyori(11) = "2200"
        CBKyori(12) = "2300"
        CBKyori(13) = "2400"
        CBKyori(14) = "2500"
        CBKyori(15) = "2600"
        CBKyori(16) = "3000"
        CBKyori(17) = "3200"
        CBKyori(18) = "3400"
        CBKyori(19) = "3600"

    ' コース
    Dim CBCource(3)
        CBCource(0) = "ダート"
        CBCource(1) = "芝"
        CBCource(2) = "障害"

    ' 各コンボボックスに設定値をセット
    Worksheets("成績表").KaisaiComb.List = CBRaceKaisai
    Worksheets("成績表").KyoriComb.List = CBKyori
    Worksheets("成績表").CourceComb.List = CBCource

End Sub

Sheet1(成績表)は、シート上に配置した各ボタンのクリックイベントに対応した ルーチンへジャンプするための処理を記述しています。

'***** データ削除 *****
Private Sub DataClr_Click()
   Call DataDelete
End Sub

'***** ファイル出力 *****
Private Sub FileOut_Click()
   Call CSVout
End Sub

'***** 実行開始 *****
Private Sub StartDB_Click()
   Call DataBase_Init
   Call SQLite(0)
End Sub

'***** 前ページ表示制御 *****
Private Sub BeforePage_Click()
   Call SQLite(0)
End Sub

'***** 次ページ表示制御 *****
Private Sub NextPage_Click()
   Call SQLite(1)
End Sub

'***** 先頭ページ表示制御 *****
Private Sub FirstPage_Click()
   Call StartDB_Click
End Sub

'***** 最終ページ表示制御 *****
Private Sub LastPage_Click()
   Call SQLite(3)
End Sub

'***** 各変数の初期化 *****
Private Sub DataBase_Init()
   StartPoint = 0
   PageNo = 0
   PageCount = 0
   BackPoint = 0
   ReadRec = 0
   DispRec = 0
   N_Page = 0
   N_Num = 0
   B_Page = 0
   B_Num = 0
   LastPage = 0
   StartFLG = 0
   KeepPage = 0
End Sub

標準モジュール : seisekiはメインとなる処理を記述しています。 ソースコードは「Excelでデータベース(SQLite3)を扱う」 で紹介しているものがベースとなっています。処理の大部分は、ページ制御部分であり、実際にデータベースからのデータ抽出と表示部分は データベースの項目数(フィールド)の数だけ設定してループを回しているだけです。 処理の流れは、データベースオープン→テーブルセット→SQL文(クエリ)発行→ループでデータ表示といった流れになっています。 ルーチンの重複がありますが、外部データへの出力も同じで、抽出したデータをカンマ区切りとしてテキスト形式(CSV)で書き出しています。 尚、参考補足事項ですが、出力されたCSVファイルをダブルクリックしてExcelとの関連付け起動させないでください。Excelのセルの書式(属性) に自動で調整されて、日付形式などの意図しない形式で表示されてしまいます。データの確認は、メモ帳などのテキストエディタで確認して下さい。
参考として、データをExcelに取り込む場合は、メニューのデータから、リボンのデータの取得もしくは、テキストまたはCSVから実施して下さい。 Excelのバージョンによってリボンの名称や配置などが異なるかと思いますが、同じような機能があると思います。

筆者は、Windows10のMicrosoft365版のExcelを利用していますが、データの取り込みが従来のインポートがなくなっていて、Power Queryに なって少し操作に戸惑いました。標準では、従来のウィザードは利用できないと思っていましたが、ファイル→オプション→データ項目に レガシーデータインポートウィザードという項目があり、テキストから(レガシー)にチェックを入れると従来方式のウィザードが利用できました。
下記のいずれかの方法でCSVデータのインポートをして下さい。(参考)

'*********************************************************************************
'*
'*      レース成績表データベース検索処理
'*
'*
'*      ●Pegasus.db(SQLite3)利用によるレース成績表データベース検索
'*
'*
'*********************************************************************************

'***** グローバル変数 *****
Public My_Row    As Long        ' 行位置
Public My_Col    As Long        ' 列位置
Public StarPoint As Integer     ' レコード開始位置
Public PageNo    As Integer     ' ページ番号
Public PageCount As Integer     ' ページカウンタ
Public BackPoint As Integer     ' 前ページ開始位置
Public B_Page    As Integer     ' 前ページ開始位置一時保存
Public B_Num     As Integer     ' 前ページ番号一時保存
Public N_Page    As Integer     ' 次ページ開始位置一時保存
Public N_Num     As Integer     ' 次ページ番号一時保存
Public StartFLG  As Integer     ' 前ページ、次ページ判定フラグ
Public KeepPage  As Integer     ' 最終ページ番号保存用

Public filename  As String      ' DataBase FileName
Public i         As Long        ' セルの表示開始位置制御カウンタ
Public DBName    As String      ' DataBace ODBC定義 (SQLite3)
Public Sql       As String      ' SQL
Public Db        As Object      ' DataBase
Public rs        As Object      ' Recordset
   
'***** データベース処理開始 (全件表示 : 100件単位) *****
Public Sub SQLite(ByVal StartFLG As Integer)
   Dim S_PageCnt  As Integer    ' 開始ページカウンタ保存用
   Dim S_PageNum  As Integer    ' 開始ページ番号保存用
   Dim ReadRec    As Integer    ' 読み出しレコードカウンタ
   Dim DispRec    As Integer    ' 表示件数制御カウンタ
   Dim LastPage   As Integer    ' 最終ページ番号取得用
   
   On Error Resume Next
   
   '***** 前ページをセット *****
   If StartFLG = 0 Then
      S_PageCnt = B_Page
      S_PageNum = B_Num
   End If
   '***** 次ページをセット *****
   If StartFLG = 1 Then
      S_PageCnt = N_Page
      S_PageNum = N_Num
   End If
   '***** 最終ページをセット *****
   If StartFLG = 3 Then
      S_PageCnt = (KeepPage * PageCount) - PageCount + 1
      S_PageNum = KeepPage
   End If
   
   '***** 画面クリア *****
   Call DataDelete
   
   '***** DB FileName設定 (※変更のこと) *****
   If Dir(ThisWorkbook.Path & "¥pegasus.db") = "" Then
      MsgBox "データベースファイルが存在しません。"
      Exit Sub
   End If
   '***** データベースオープン *****
   Call SQLiteDB_Open("pegasus.db")

   '***** コンボボックスの各設定値をセット *****
   Kaisai = Worksheets("成績表").KaisaiComb.Text
   cource = Worksheets("成績表").CourceComb.Text
   sKyori = Worksheets("成績表").KyoriComb.Text

   '***** SQL文を発行 *****
   Sql = "SELECT * FROM seisekidb WHERE KeiBabajyou COLLATE NOCASE LIKE '%" & Kaisai & "%'" _
         & " AND Cource COLLATE NOCASE LIKE " & "'" & cource & "%'" _
         & " AND Kyori COLLATE NOCASE LIKE " & "'%" & sKyori & "%'" _
         & " ORDER BY ID ASC LIMIT 5000"
         
   '***** テーブルセット *****
   Call Table_Set
   
   '***** 抽出レコード件数 *****
   RecCount = rs.RecordCount
   Range("B4") = RecCount
   If RecCount = 0 Then
      Call DB_Close
      MsgBox "対象データがありませんでした。"
      Exit Sub
   End If
   
   '***** 画面の表示更新停止開始 *****
   Application.ScreenUpdating = False
   
   '***** ページ制御カウンタ *****
   StartPoint = S_PageCnt
   PageNo = S_PageNum
   PageCount = 100
   BackPoint = StartPoint - PageCount
   ReadRec = 0
   DispRec = 0

   '***** 初期値確認 (StartPoint) *****
   If StartPoint = 0 Then
      StartPoint = 1
      PageNo = 1
      Worksheets("成績表").BeforePage.Enabled = False
      Worksheets("成績表").FirstPage.Enabled = False
   End If
   '***** 初期値確認 (PageNo) *****
   If PageNo = 0 Then
      PageNo = 1
      Worksheets("成績表").BeforePage.Enabled = False
      Worksheets("成績表").FirstPage.Enabled = False
   End If
   '***** ページ番号を表示 *****
   Range("A4") = PageNo
   '***** 最終ページ番号 *****
   LastPage = (RecCount / PageCount) + 1

   '***** 最終ページ保存 *****
   If RecCount <= 100 Then LastPage = LastPage - 1
   KeepPage = LastPage
   Range("C4") = PageNo & " / " & KeepPage

   If rs.EOF Then
      StartPoint = 0
      PageNo = 0
      PageCount = 0
      BackPoint = 0
      ReadRec = 0
      DispRec = 0
      StartFLG = 0
      
      '***** 全制御ボタンを不活性化 *****
      Worksheets("成績表").BeforePage.Enabled = False
      Worksheets("成績表").NextPage.Enabled = False
      Worksheets("成績表").FirstPage.Enabled = False
      Worksheets("成績表").LastPage.Enabled = False
   Else
      '▼▼▼▼ 結果をセルに書き込む (表示) ▼▼▼▼
      i = 6  ' 表示開始位置 : 6行目~105行目
      Do Until rs.EOF = True
         ' 読み込みレコードカウンタ
         ReadRec = ReadRec + 1
         ' データ開始レコードまで読み飛ばし
         If StartPoint <= ReadRec Then
            ' 設定(100件/頁)になったら表示を終了
            If DispRec = PageCount Then
               Worksheets("成績表").NextPage.Enabled = False
               Exit Do
            End If
            ' 表示レコードカウンタ
            DispRec = DispRec + 1
      
            '============= 結果の表示 ==========================================
            Cells(i, 1).Value = ReadRec                ' No.      (ReadRec)
            Cells(i, 2).Value = rs.Fields(1).Value     ' 日付     (RaceDate)
            Cells(i, 3).Value = rs.Fields(2).Value     ' コード   (BabaCode)
            Cells(i, 4).Value = rs.Fields(3).Value     ' R番号    (RaceNo)
            Cells(i, 5).Value = rs.Fields(4).Value     ' 競馬場   (KeiBabajyou)
            Cells(i, 6).Value = rs.Fields(5).Value     ' 開催     (Kaisai)
            Cells(i, 7).Value = rs.Fields(6).Value     ' 発走時間 (StartTime)
            Cells(i, 8).Value = rs.Fields(7).Value     ' 天気     (Tenki)
            Cells(i, 9).Value = rs.Fields(8).Value     ' 馬場     (Baba)
            Cells(i, 10).Value = rs.Fields(9).Value    ' レース名 (RaceName)
            Cells(i, 11).Value = rs.Fields(10).Value   ' コース   (Cource)
            Cells(i, 12).Value = rs.Fields(11).Value   ' 距離     (Kyori)
            Cells(i, 13).Value = rs.Fields(12).Value   ' 単勝     (TanSyou)
            Cells(i, 14).Value = rs.Fields(13).Value   ' 枠連     (Wakulen)
            Cells(i, 15).Value = rs.Fields(14).Value   ' 馬連     (Umalen)
            Cells(i, 16).Value = rs.Fields(15).Value   ' 馬単     (UmaTan)
            Cells(i, 17).Value = rs.Fields(16).Value   ' 3連単    (SanlenTan)
            Cells(i, 18).Value = rs.Fields(17).Value   ' 1着      (OneUma)
            Cells(i, 19).Value = rs.Fields(18).Value   ' 2着      (TwoUma)
            Cells(i, 20).Value = rs.Fields(19).Value   ' 3着      (ThreeUma)
            Cells(i, 21).Value = rs.Fields(20).Value   ' 頭数     (Tousu)
            ' カウントアップ
            i = i + 1
         End If
         rs.MoveNext
      Loop
      
      '***** 画面の表示更新停止解除 *****
      Application.ScreenUpdating = True

      '***** レコードの開始位置 *****
      StartPoint = PageCount * PageNo + 1
   
      '***** ページ制御 *****
      '***** 前ページの場合 *****
      If PageNo > 1 Then
         Worksheets("成績表").BeforePage.Enabled = True
         Worksheets("成績表").FirstPage.Enabled = True
         StartFLG = 0
         B_Page = BackPoint
         B_Num = PageNo - 1
      End If
      '***** 次ページの場合 *****
      If PageNo < LastPage Then
         Worksheets("成績表").NextPage.Enabled = True
         Worksheets("成績表").LastPage.Enabled = True
         StartFLG = 1
         N_Page = StartPoint
         N_Num = PageNo + 1
      End If

   End If
   '***** 前ページボタン不活性化 *****
   If PageNo = 1 Then
      Worksheets("成績表").BeforePage.Enabled = False
      Worksheets("成績表").FirstPage.Enabled = False
   End If
   '***** 次ページボタン不活性化 *****
   If PageNo >= LastPage Then
      Worksheets("成績表").NextPage.Enabled = False
      Worksheets("成績表").LastPage.Enabled = False
   End If

   '***** 画面更新の実行 *****
   Application.ScreenUpdating = True
   Range("B4").Select
    
   '***** 接続を閉じる *****
   Call DB_Close
   Range("A1").Select
End Sub

'***** 抽出ファイル出力 *****
Sub CSVout()
  Dim buf, StrTemp As String
  Dim FNAME As String

   '***** DB FileName設定 (※変更のこと) *****
   If Dir(ThisWorkbook.Path & "¥pegasus.db") = "" Then
      MsgBox "データベースファイルが存在しません。"
      Exit Sub
   End If
   '***** データベースオープン *****
   Call SQLiteDB_Open("pegasus.db")

   '***** コンボボックスの各設定値をセット *****
   Kaisai = Worksheets("成績表").KaisaiComb.Text
   cource = Worksheets("成績表").CourceComb.Text
   sKyori = Worksheets("成績表").KyoriComb.Text

   '***** SQL文を発行 *****
   Sql = "SELECT * FROM seisekidb WHERE KeiBabajyou COLLATE NOCASE LIKE '%" & Kaisai & "%'" _
         & " AND Cource COLLATE NOCASE LIKE " & "'" & cource & "%'" _
         & " AND Kyori COLLATE NOCASE LIKE " & "'%" & sKyori & "%'" _
         & " ORDER BY ID ASC LIMIT 5000"
         
   '***** テーブルセット *****
   Call Table_Set
   
   '***** 抽出レコード件数 *****
   RecCount = rs.RecordCount
   Range("B4") = RecCount
   If RecCount = 0 Then
      Call DB_Close
      MsgBox "対象データがありませんでした。"
      Exit Sub
   End If

   Do Until rs.EOF = True
          '***** バッファにカンマ区切りのデータをセット *****
          StrTemp = rs.Fields(1).Value & "," & _
                    rs.Fields(2).Value & "," & _
                    rs.Fields(3).Value & "," & _
                    rs.Fields(4).Value & "," & _
                    rs.Fields(5).Value & "," & _
                    rs.Fields(6).Value & "," & _
                    rs.Fields(7).Value & "," & _
                    rs.Fields(8).Value & "," & _
                    rs.Fields(9).Value & "," & _
                    rs.Fields(10).Value & "," & _
                    rs.Fields(11).Value & "," & _
                    rs.Fields(12).Value & "," & _
                    rs.Fields(13).Value & "," & _
                    rs.Fields(14).Value & "," & _
                    rs.Fields(15).Value & "," & _
                    rs.Fields(16).Value & "," & _
                    rs.Fields(17).Value & "," & _
                    rs.Fields(18).Value & "," & _
                    rs.Fields(19).Value & "," & _
                    rs.Fields(20).Value & vbCrLf

            ' レコードを加算
            buf = buf + StrTemp
         rs.MoveNext
   Loop

   '***** 抽出対象ファイルが無い場合 *****
   If buf = "" Then
      MsgBox "抽出対象ファイルがありません。"
      Call DB_Close
      Exit Sub
   End If
   '***** ファイル名を合成 (年月日時分秒) *****
   FNAME = "Seiseki_" & Year(Date) & Right("0" & Month(Date), 2) & Right("0" & Day(Date), 2) & _
            Right("0" & Hour(Time), 2) & Right("0" & Minute(Time), 2) & Right("0" & Second(Time), 2) & ".csv"

   Open ThisWorkbook.Path & "¥" & FNAME For Output As #1
   Print #1, buf
   Close #1

   MsgBox "ファイルに " & RecCount & "件 出力しました。"

   '***** 接続を閉じる *****
   Call DB_Close
End Sub

'***** データベースオープン *****
Sub SQLiteDB_Open(ByVal DBSetName As String)
   filename = ThisWorkbook.Path & "¥pegasus.db"
   DBName = "DRIVER=SQLite3 ODBC Driver;Database=" & filename & ";"
   Set Db = CreateObject("ADODB.Connection")
   Db.CursorLocation = 3
   Db.Open DBName
End Sub

'***** テーブルセット *****
Sub Table_Set()
   Set rs = CreateObject("ADODB.Recordset")
   rs.Open Sql, Db, 3, 3
   Set rs = Db.Execute(Sql)
End Sub

'***** データベースクローズ *****
Sub DB_Close()
   rs.Close
   Db.Close
   Set rs = Nothing
   Set Db = Nothing
End Sub

'***** データ消去 *****
Sub DataDelete()
   Sheets("成績表").Select
   Worksheets("成績表").Activate
   If Range("A6") <> "" Then
      Application.ScreenUpdating = False
      Range("A6:U113").SpecialCells(xlCellTypeConstants, 23).ClearContents
      Range("A4:C4").Value = ""
      Application.ScreenUpdating = True
   End If
End Sub

3.ダウンロード

提供するソースコードのライセンスは、CC0 (クレジット表示不要、改変可、商用可) とします。自由に利用して頂いてかまいません。
下記のファイルをアーカイブにして提供します。データは、著作権に触れる恐れがあるため、配布することができません。 動作確認のテスト用のサンプルとして100件のみ入れてあります。実際に利用する場合は、各自で取得して新規に作成願います。 尚、データの取得やプログラム実行において損害等が生じた場合は、筆者は一切の責任も負いません。全て自己責任でお願いします。
    ・import.bat
    ・pegasus.db
    ・raceseiseki.exe
    ・raceseiseki.hsp
    ・sqlite3.dll (raceseiseki.exeを実行するのに必要)
    ・Yahoo競馬結果リンク先取得.xlsm
    ・Yahoo競馬レース結果取得.xlsm
    ・Yahoo競馬レース成績表検索.xlsm
    ・ヘッダー名.txt
「ツール-HSP編」で予定しているHSPのツールとソースも同梱しています。

ダウンロード

■関連記事
・Excelでデータベース(SQLite3)を扱う
・複数のファイルをマージする
・競馬成績表データベースを作る(事前準備編)
・競馬成績表データベースを作る(データ取得編)
・競馬成績表データベースを作る(データベース編)
・競馬成績表データベースを作る(ツール-HSP編)

コメント

このブログの人気の投稿

Excelアドインで日本語形態素解析

階層構造JSONファイルの作成

HSPでコマンドプロンプトを制御する

TOP