3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C#でExcelアドイン × PostgreSQL × VBA: ExcelでPostgreSQLを扱うTips

Last updated at Posted at 2024-11-08

ExcelアドインでPostgreSQLに接続する実装について、より詳しく解説した記事を作成します。

ExcelからPostgreSQLに接続するアドインの開発 - 実装詳解

はじめに

ExcelからPostgreSQLデータベースに接続し、SQLクエリを実行して結果をExcelシートに書き込む方法を紹介します。ODBCドライバをインストールできない環境でも動作するよう、C#とExcel DNAライブラリを使ってExcelアドインを作成します。この記事では、特にC#の実装部分について詳しく解説します。

必要な環境とライブラリ

開発環境

  • Visual Studio 2019以降
  • .NET Framework 4.7.2以降
  • Microsoft Excel (2013以降推奨)

必要なNuGetパッケージ

- ExcelDna.AddIn
- ExcelDna.Integration
- Npgsql
- Microsoft.Office.Interop.Excel

実装の詳細解説

1. 基本構造とクラス設計

using System;
using System.Data;
using System.Runtime.InteropServices;
using Npgsql;
using ExcelDna.Integration;
using Excel = Microsoft.Office.Interop.Excel;

namespace PostgresExcelAddin
{
    public static class Functions
    {
        private static NpgsqlConnection _connection;
        // ...
    }
}

この部分で重要なポイント:

  • ExcelDna.Integration名前空間:Excel DNAの機能を使用するために必要
  • Npgsql:PostgreSQL接続用のライブラリ
  • Microsoft.Office.Interop.Excel:ExcelのCOMインターフェース用
  • static NpgsqlConnection _connection:データベース接続を保持する静的フィールド

2. データベース接続機能の実装

[ExcelFunction(Description = "PostgreSQLに接続します")]
public static string ConnectDB(string host, string database, string username, string password, string port = "5432")
{
    try
    {
        var connectionString = $"Host={host};Port={port};Database={database};Username={username};Password={password}";
        
        // 既存の接続をクリーンアップ
        if (_connection != null && _connection.State == ConnectionState.Open)
        {
            _connection.Close();
            _connection.Dispose();
        }

        // 新しい接続を確立
        _connection = new NpgsqlConnection(connectionString);
        _connection.Open();
        return "接続成功";
    }
    catch (Exception ex)
    {
        return $"接続エラー: {ex.Message}";
    }
}

重要なポイント:

  • [ExcelFunction]属性:この関数をExcelから呼び出し可能にする
  • 接続文字列の構築:セキュリティ上の理由から、パラメータ化された方式を使用
  • 既存接続の適切な破棄:メモリリークを防ぐ
  • エラーハンドリング:例外をキャッチしてユーザーフレンドリーなメッセージを返す

3. データベース切断機能

[ExcelFunction(Description = "PostgreSQLから切断します")]
public static string DisconnectDB()
{
    try
    {
        if (_connection != null)
        {
            if (_connection.State == ConnectionState.Open)
            {
                _connection.Close();
            }
            _connection.Dispose();
            _connection = null;
        }
        return "切断成功";
    }
    catch (Exception ex)
    {
        return $"切断エラー: {ex.Message}";
    }
}

実装のポイント:

  • 接続状態のチェック
  • リソースの適切な解放
  • null参照の防止

4. クエリ実行機能

[ExcelFunction(Description = "SQLクエリを実行してシートに結果を書き込みます")]
public static object ExecuteQuery(string query, string sheetName)
{
    try
    {
        // 接続チェック
        if (_connection == null || _connection.State != ConnectionState.Open)
        {
            return "データベースに接続されていません";
        }

        // Excel操作のための準備
        var app = ExcelDnaUtil.Application as Excel.Application;
        Excel.Worksheet sheet;

        // シートの取得または作成
        try
        {
            sheet = app.ActiveWorkbook.Worksheets[sheetName];
        }
        catch
        {
            sheet = app.ActiveWorkbook.Worksheets.Add();
            sheet.Name = sheetName;
        }

        // クエリ実行とデータ取得
        using (var cmd = new NpgsqlCommand(query, _connection))
        using (var reader = cmd.ExecuteReader())
        {
            var dataTable = new DataTable();
            dataTable.Load(reader);

            // シートのクリア
            sheet.UsedRange.Clear();

            // ヘッダーの書き込み
            for (int i = 0; i < dataTable.Columns.Count; i++)
            {
                sheet.Cells[1, i + 1].Value = dataTable.Columns[i].ColumnName;
            }

            // データの一括書き込み
            var data = new object[dataTable.Rows.Count, dataTable.Columns.Count];
            for (int row = 0; row < dataTable.Rows.Count; row++)
            {
                for (int col = 0; col < dataTable.Columns.Count; col++)
                {
                    data[row, col] = dataTable.Rows[row][col];
                }
            }

            if (dataTable.Rows.Count > 0)
            {
                var range = sheet.Range[
                    sheet.Cells[2, 1], 
                    sheet.Cells[dataTable.Rows.Count + 1, dataTable.Columns.Count]
                ];
                range.Value = data;
            }

            // 列幅の自動調整
            sheet.Columns.AutoFit();
            return $"{dataTable.Rows.Count}行のデータを取得しました";
        }
    }
    catch (Exception ex)
    {
        return $"エラー: {ex.Message}";
    }
}

実装の重要ポイント:

  1. データ取得フロー

    • NpgsqlCommandの作成
    • DataReaderを使用したデータ読み取り
    • DataTableへのデータロード
  2. Excel操作

    • シートの存在確認と作成
    • 既存データのクリア
    • ヘッダー行の設定
    • データの一括書き込み(パフォーマンス最適化)
    • 列幅の自動調整
  3. エラーハンドリング

    • データベース接続状態の確認
    • Excel操作時の例外処理
    • ユーザーフレンドリーなエラーメッセージ

5. 更新系クエリ実行機能

[ExcelFunction(Description = "UPDATE/INSERT/DELETEクエリを実行します")]
public static string ExecuteNonQuery(string query)
{
    try
    {
        if (_connection == null || _connection.State != ConnectionState.Open)
        {
            return "データベースに接続されていません";
        }

        using (var cmd = new NpgsqlCommand(query, _connection))
        {
            int result = cmd.ExecuteNonQuery();
            return $"{result}行が影響を受けました";
        }
    }
    catch (Exception ex)
    {
        return $"エラー: {ex.Message}";
    }
}

実装のポイント:

  • 更新系クエリの実行にはExecuteNonQueryを使用
  • 影響を受けた行数を返却
  • 適切なリソース管理(usingステートメント)

VBAからの呼び出し方法

ExcelのVBAからC#で実装した関数を呼び出す例:

' データベース接続
Sub ConnectToDatabase()
    Dim result As String
    result = Application.Run("ConnectDB", "localhost", "postgres", "username", "password", "5432")
    MsgBox result
End Sub

' クエリ実行
Sub ExecuteQueryExample()
    Dim queryResult As String
    queryResult = Application.Run("ExecuteQuery", "SELECT * FROM users", "Results")
    MsgBox queryResult
End Sub

' データベース更新
Sub UpdateDatabase()
    Dim nonQueryResult As String
    nonQueryResult = Application.Run("ExecuteNonQuery", "UPDATE users SET active = true WHERE id = 1")
    MsgBox nonQueryResult
End Sub

' 切断処理
Sub DisconnectFromDatabase()
    Dim disconnectResult As String
    disconnectResult = Application.Run("DisconnectDB")
    MsgBox disconnectResult
End Sub

アドイン開発時の注意点

  1. デバッグ方法

    • Visual StudioでExcelプロセスにアタッチして実行時デバッグが可能
    • デバッグプリント文はDebug.WriteLine()を使用
  2. エラーハンドリング

    • すべての公開メソッドで適切な例外処理を実装
    • ユーザーフレンドリーなエラーメッセージを返す
    • デバッグ情報は開発時のみ表示
  3. パフォーマンス最適化

    • 大量データ処理時は一括書き込みを使用
    • 接続のプーリングを考慮
    • 不要なシート操作を最小限に
  4. セキュリティ考慮事項

    • 接続文字列の安全な管理
    • SQL injection対策
    • エラーメッセージでの機密情報漏洩防止

まとめ

このExcelアドインの実装により、以下のメリットが得られます:

  1. ODBCドライバ不要でPostgreSQLに接続可能
  2. C#の型安全性とエラーハンドリングの恩恵
  3. Excel DNAによる簡単な関数エクスポート
  4. 効率的なデータ取得と書き込み

また、この実装は以下の点で拡張可能です:

  • パラメータ化クエリのサポート
  • トランザクション管理の追加
  • 非同期処理への対応
  • より詳細なエラーログ機能

このアドインは、ExcelユーザーがPostgreSQLデータベースを簡単に操作できるようにする強力なツールとなります。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?