4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Electronでアプリ作成3 ElectronでSqlite3を操作

Posted at

 Node.js環境でブラウザベースのアプリが作成できるElectronですが、結構メジャーなアプリがElectronベースで作られているようでね。そんなElectornで取り扱いが簡単なデータベースのSqlite3が操作できたら、いろいろ便利だろうと思い、サンプルとなるアプリを作成しましのたで、投稿します。自分の知識不足で、結構ハマってしまった個所もありましが、とりあえずはデータの挿入、抽出は確認できています。

動作確認環境

Windows11
node.js v18.18.1
electron v27.0.0
sqlite3 3.43.0

参考になる記事、サイト等

Electronアプリの作成については過去の記事で触れてもらっています。

WindowsにSQLite3をインストールしています。こちらのサイト参考にさせてもらいました。大変丁寧でわかりやすかったです。

データ表示をgrid.jsにさせています。以下参考にどうそ。

準備

Electronアプリを作成できるよう準備しておきます。

また、sqlite3をインストールしておきます。

npm install -S sqlite3

ただし、exeのビルドの際にpakage.jsonのdependenciesにsqlite3が載っていないと実行時にエラーがでてしまいました。手動で修正しました。

pakage.json
  "dependencies": {
    "electron-squirrel-startup": "^1.0.0",
    "sqlite3": "^5.1.6"
  }

コードについて

・preload.hs
・index.js
・main.js
の3つのファイルを編集しています。以下コードを掲載しておきます。

preload.js

preload.js
// レンダラーからNode.jsにアクセスするためのファイル
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('dbOp', {
    createDb: async () => ipcRenderer.invoke('createDb'),    //データベース作成
    selectAll: async () => ipcRenderer.invoke('selectAll'),  //SELECT *
    insertData: async (memoText) => ipcRenderer.invoke('insertData', memoText), //データを挿入
});

main.js

main.js
// main.jsはNode.jsにて動作する requireにてelectronモジュールを読み込んでいる
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const sqlite3 = require('sqlite3');
const db = new sqlite3.Database("./my_database.db");

// ウィンドウの作成準備
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,   //ウィンドウサイズ
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'), //プレローダーの指定
    }
  });
  // 読み込むファイル
  win.loadFile('index.html');
  // デベロッパーツールを開く 不要ならコメントアウト
  // win.webContents.openDevTools();
  // メニューバーの非表示
  win.setMenuBarVisibility(false);
}

// ウィンドウ初期化時
app.whenReady().then(() => {
  // テーブル作成 第2引数asyncでうまく戻り値拾えず。ちゃんとnew Promiseで記述しています。
  ipcMain.handle('createDb', (eve) =>
    new Promise((resolve, reject) => {
      db.run('CREATE TABLE IF NOT EXISTS my_memo ([id] integer primary key autoincrement, [memo] text, [date_time] datetime);', err => {
        if (err) reject(err);
        resolve();
      });
    }));

  // SELECT文でのデータ取得
  ipcMain.handle('selectAll', (eve) =>
    new Promise((resolev, reject) => {
      db.serialize(() => {
        db.all('SELECT * FROM my_memo', (err, rows) => {
          if (err) reject(err);
          resolev(rows);
        });
      });
    })
  );

  // データ挿入
  ipcMain.handle('insertData', (eve, memoText) =>
    new Promise((resolev, reject) => {
      db.run('INSERT INTO my_memo (memo, date_time) VALUES (? , datetime("now", "localtime"));', memoText, err => {
        if (err) reject(err);
        resolev();
      });
    })
  )

  // ウィンドウの表示
  createWindow();
  // macOS用
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  })
})

// ウィンドウのクローズ
app.on('window-all-closed', () => {
  db.close();
  if (process.platform !== 'darwin') app.quit();
})

index.html

index.html
<!DOCTYPE html>
<html>

<head>
  <meta charset='UTF-8' />
  <title>ElectronでSqlite3</title>
  <!-- データ表示にGrid.jsを利用 -->
  <link rel='stylesheet' href='https://unpkg.com/gridjs/dist/theme/mermaid.min.css'>
  <script src='https://unpkg.com/gridjs/dist/gridjs.umd.js'></script>
</head>

<body>
  <h1>ElectronでSqlite</h1>
  <p>テキストをSqlite3にて記録するサンプルです</p>
  <div>
    <input type='text' id="memoInput">
    <input type='button' id='insertBtn' value='書込み'>
  </div>
  <div id='gridTag'></div>

  <script>
    // テーブル作成 即時関数として呼出し
    window.dbOp.createDb()
      .catch(err => { console.log(err) });

    // 起動時にメモをgridに表示
    let grid; // Grid.jsオブジェクト
    window.dbOp.selectAll()
      .then(ret => {
        ret.forEach((elem) => { delete elem.id });  //キー:idを削除
        grid = new gridjs.Grid({
          data: ret
        }).render(document.getElementById('gridTag'));
      })
      .catch(err => { console.log(err) });

    // ボタンクリック時
    document.getElementById('insertBtn').onclick = () => {
      // メモを書き込む
      const memoText = document.getElementById('memoInput').value;
      if (memoText) {
        window.dbOp.insertData(memoText)
          .catch(err => { console.log(err) });
      }
      document.getElementById('memoInput').value = "";

      // メモをgridに表示
      window.dbOp.selectAll()
        .then(ret => {
          ret.forEach((elem) => { delete elem.id });  //キー:idを削除
          grid.updateConfig({
            data: ret
          }).forceRender();
        })
        .catch(err => { console.log(err) });
    }
  </script>
</body>

</html>

テキストボックスに記入した文字がデータベースに保存されます。アプリ起動時と、ボタン押下時に、SELECT文を実行して、更新しています。データベースファイルははプロジェクトフォルダまたは、実行ファイルと同じフォルダに自動で作成されますが、絶対パスで指定しておくこともできます。

image.png

以上ご参考まで。

4
5
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
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?