ゆるふわエンジニアのブログ

行ったこと、調べたこと等をつらつらと書いていくかもしれません。

JavaScriptでExcelライクなグリッドを使う(Handsontable)

JavaScriptExcelライクなグリッドを使用するための
ライブラリである、Handsontableについて書いていきます。

本ブログの内容です。

Handsontableのダウンロード

以下のページからソースコードをダウンロードしてください。
使用するファイルは、distフォルダの中に入っています。
github.com

ライセンス

MITライセンスです。
github.com

サンプルコード

サンプルコードにjQueryを使用していますが、
HandsontableがjQueryに依存しているわけではないです。

HTML

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">        
    <link rel="stylesheet" href="css/handsontable.full.min.css" />
    <script src="js/jquery-3.3.1.min.js"></script>
    <script src="js/handsontable.full.min.js"></script>
    <script src="js/index.js"></script>
</head>
<body>
    <div id="grid"></div>
</body>
</html>

JavaScript

$(function() {
    var data = [
        ['佐藤', 28],
        ['鈴木', 19],
        ['田中', 25]
      ];
      
    var grid = document.getElementById('grid');
    
    new Handsontable(grid, 
    {
        data: data
    });
});

使い方

公式ドキュメントと、有志の方が書かれた日本語情報のページを紹介します。

公式ドキュメント

Handsontable - Tutorial: Introduction

日本語情報

Handsontable 使い方メモ1(基本)
Handsontable 使い方メモ2(グリッドのオプション)
Handsontable 使い方メモ3(カラム・セルオプション)
Handsontable 使い方メモ4(メソッド)

気になった記事メモ

API

Zalando RESTful API と イベントスキーマのガイドライン

アニメーション

カッコ良すぎる!CSSとJavaScriptで作られた真似してみたいアニメーションロゴ10選 - Web Design Facts
実装がどんどん簡単になっている!スクロールに連動するCSSアニメーションを与えるスクリプト -Delighters | コリス

JavaScript

JavaScript の async/await の仕様をずっと誤解していた

Docker

「Dockerによるアプリケーション開発環境構築ガイド」はプロのエンジニア必読の一冊だ(断言) - Lean Baseball

工数見積り

工数見積もりのコツ

英語

プログラマのための「英語でググる技術」|英語で最新情報を手に入れよう – Crowdtech SQUARE[クラウドテック スクエア]

フリーランス

フリーランスに月10万の仕事保証——ランサーズが「ベーシックワーク」実験をスタート | BUSINESS INSIDER JAPAN
フリーランスエンジニアが仕事を増やすには、やっぱり技術ブログが良い | フリーランスumentuのサイト
続・フリーランスエンジニアが仕事を増やすには、やっぱり技術ブログが良い | フリーランスumentuのサイト

フリーランスが加入できる健康保険について

フリーランスが加入できる健康保険について調べたので、
いろいろとメモがてら残しておきます。

お品書き。

フリーランスが入れる健康保険の種類

以下の3種類があるようです。

以下で、それぞれについて説明していきます。

国民健康保険

加入するのに特に条件の無さそうな一般的な保険。
手続きの提出期限が
退職した翌日(社会保険の喪失日)から14日以内
なので、要注意ですね。

任意継続被保険者制度

退職してからも在職中と同じ健康保険に引き続き加入でき、
同様の被保険者資格を保持し続けることができる保険。
これは手続きの提出期限が
退職後20日以内
なので、国民健康保険よりはちょっと緩い。
でも、会社を辞めた人のみが受けられる特権みたいなものなので、
誰でも入れるわけではないです。

健康保険組合

決まった職業に従事する人が加入できる限定された健康保険。
これは
文芸美術国民健康保険組合
に加入するのがよくあるパターンみたいですね。
加入条件は、職業欄に「WEBデザイナ」と書いておき、
後は作成物(成果物)があれば良いみたいです。
こちらの手続きの提出期限は無い模様。

どれがお得か?

ざっと調べていると
健康保険組合 < 任意継続被保険者制度 < 国民健康保険
の順に安いという様に書かれている記事が多いですね。

ですが、上記の健康保険組合に入るパターンだと、
健康保険自体は安くても、個人事業税が掛かるため、
トータルでは任意継続被保険者制度とあまり変わらなくなることもあるようです。
ちなみに、個人事業税については、
「個人事業税 [住んでいる都道府県名]」
で検索を行えばヒットします。
WEBデザイナはデザイン業にあたるようです。
SEやプログラマも、ソフトウェアを製造するという認識で
製造業にあたるかもしれないとかいう話もあります。
上記を踏まえ、任意継続被保険者制度が一番安いかといえば、
国民健康保険の方が安いパターンもあるとかなんとか。

結局、どれが一番良いのか?

自分で調べて比較し、一番安いのを選びましょう。
任意継続被保険者制度と国民健康保険の比較については、
市役所(区役所)の窓口へ行けば、どちらの方が安いのか
教えてもらえるみたいです。

参考にしたページ

独立する際、ITフリーランスが加入できる健康保険まとめ|フリーランスITエンジニアの案件・求人【geechs job(ギークスジョブ)】
フリーランスの個人事業税は『誰がいつ誰にいくらどのように』納めるの? | 融資×経理でシゴトを強く|モロトメジョー税理士事務所 | 横浜
個人事業税 - 愛知県

freeeを利用して開業届を作成、提出した話

本日、freeeの開業届け作成サービスを利用し、
開業届けを作成、税務署へ提出してきました。

www.freee.co.jp

とりあえず、職業はフリーランス
仕事の概要はITサービス・ソフトウェア開発と設定しました。
(上記は、freeeで項目を選択した時の初期設定値です。)
職業等は、後から変更できるっぽいので、ザックリと設定しています。

来月からは一時的にかずっとかはわかりませんが、
フリーランスエンジニア、プログラマとして活動することになります。

これからは、アウトプットやブランディングに力を入れていかないとな...

PetaPocoを触ってみた(導入、簡単な操作編)(Micro-ORM)

Micro-ORMのPetaPocoを触ってみたので、記事として残しておきます。
サンプルコードはすべてC#で書いています。

お品書き

PetaPocoについて

PetaPoco - Topten Software

インストール

以下のコマンドをパッケージマネージャコンソールで実行するだけです。

Install-Package PetaPoco -Version 5.1.244

バージョンを指定しないと古いバージョンのものが
インストールされてしまいますので、注意してください。
最新バージョンは以下URL先で確認することができます。
www.nuget.org

簡単な操作方法

コネクション作って、App.configの情報を元に接続して、
トランザクション開始して、各操作を行い、
最後に接続を切断しています。
Insert、Update、Deleteは、上記以外にコミット、ロールバックを行っていますね。
例外が発生しなければコミット、
例外が発生したらロールバックという実装にしています。

使用しているEntityクラス

クラス名はテーブル名と同じ、プロパティ名は列名と同じにしてあります。

class USER_MASTER
{
    public string USER_ID { get; set; }
    public string DEPT_NO { get; set; }
    public string USER_NAME { get; set; }
    public DateTime? CREATED_ON { get; set; }
    public DateTime? MODIFIED_ON { get; set; }
}

Select

// 接続情報作成、接続
using(var db = new Database(connectionName))
{
    try
    {
        // トランザクション開始
        db.BeginTransaction();
        
        // Select
        var sql = @"SELECT * FROM USER_MASTER";
        var rows = db.Query<USER_MASTER>(sql);
        // Select(単一レコード)
        var sqlSingleRecord = @"SELECT * FROM USER_MASTER WHERE USER_ID = @USER_ID";
        var row = db.Query<USER_MASTER>(sqlSingleRecord, new { USER_ID = "0001" });
        // Select(特定列)
        var sqlFirstColumn = @"SELECT COUNT(1) FROM USER_MASTER";
        var count = db.ExecuteScalar<int>(sqlFirstColumn);
    }
    finally
    {
        // トランザクション終了(コミット)
        db.CompleteTransaction();
    }
}

Insert

// 接続情報作成、接続
using (var db = new Database(connectionName))
{
    try
    {
        // トランザクション開始
        db.BeginTransaction();

        // SQL文無しでInsert
        // テーブル名
        var tableName = "USER_MASTER";
        // Insert用インスタンス作成
        var insertObjNonSQL = new USER_MASTER() { USER_ID = "9999", DEPT_NO = "9999" };
        // Insert実行
        db.Insert(tableName, insertObjNonSQL);

        // SQL文有りでInsert
        // SQL文作成
        var sql = @"INSERT INTO USER_MASTER ( USER_ID, DEPT_NO ) VALUES ( @USER_ID, @DEPT_NO)";
        // Insert用インスタンス作成
        var insertObjSQL = new USER_MASTER() { USER_ID = "8888", DEPT_NO = "8888" };
        // Insert実行
        db.Execute(sql, insertObjSQL);

        // コミット
        db.CompleteTransaction();
    }
    catch
    {
        // ロールバック
        db.AbortTransaction();
        throw;
    }
}

Update

コネクションやトランザクション関係の処理はInsertと同じなため、省略しています。

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでUpdate
// テーブル名
var tableName = "USER_MASTER";
// Update用インスタンス作成
var updateObjNonSQL = new USER_MASTER() { USER_ID = "9999", USER_NAME = "HOGE" };
// Update実行
db.Update(tableName, nameof(updateObjNonSQL.USER_ID), updateObjNonSQL);

// SQL文有りでUpdate
// SQL文作成
var sql = @"UPDATE USER_MASTER SET USER_NAME = @USER_NAME WHERE USER_ID = @USER_ID";
// Update用インスタンス作成
var updateObjSQL = new USER_MASTER() { USER_ID = "8888", USER_NAME = "FUGA" };
db.Execute(sql, updateObjSQL);
// コネクションやトランザクション関係の後処理(省略)

Delete

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでDelete
// テーブル名
var tableName = "USER_MASTER";
// Delete用インスタンス作成
var deleteObjNonSQL = new USER_MASTER() { USER_ID = "9999" };
// Delete実行
db.Delete(tableName, nameof(deleteObjNonSQL.USER_ID), deleteObjNonSQL);

// SQL文有りでDelete
// SQL文作成
var sql = @"DELETE FROM USER_MASTER WHERE USER_ID = @USER_ID";
// DElete用インスタンス作成
var deleteObjSQL = new USER_MASTER() { USER_ID = "8888" };
// Delete実行
db.Execute(sql, deleteObjSQL);
// コネクションやトランザクション関係の後処理(省略)


いろいろと隠蔽されており、若干コードがスッキリしますね。
Attriubteを使っていないのでアレコレ書いていますが、
Attirbuteを使うとSQL文無しでのInsert、Update、Delete時に
テーブル名や主キー列を指定してやらなくてもよくなるので、
かなり楽にかつ短くコーディングできそうです。

あと、バインド変数の記号がすべて"@"っぽいんですけども、
もしかしてDBの種類に関係なく"@"...?

DeclarativeSqlを触ってみた(導入、簡単な操作編)(ORM)

簡単にDBを操作できるライブラリを探している中で、
DapperをベースにしたDeclarativeSqlというライブラリを見つけ
触ってみたので、記事として残しておきます。
Dapperの時と同じく、サンプルコードはC#で書いています。

お品書き

DeclarativeSqlとは

以下URLでどうぞ。
GitHub - xin9le/DeclarativeSql: Attribute-based database access
blog.xin9le.net

更新情報はこちらからも。
blog.xin9le.net
DeclarativeSql v0.2.2 リリース - xin9le.net

インストール

以下のコマンドをパッケージマネージャコンソールでそれぞれ実行するだけです。

Install-Package DeclarativeSql.Core
Install-Package DeclarativeSql.Dapper

簡単な操作方法

Dapperの時と同じです。
コネクション作って、App.configの情報を元に接続して、
トランザクション開始して、各操作を行い、
最後に接続を切断しています。
Insert、Update、Deleteは、上記以外にコミット、ロールバックを行っていますね。
例外が発生しなければコミット、
例外が発生したらロールバックという実装にしています。

使用しているEntityクラス

Dapper記事の時と同じく、クラス名はテーブル名と同じ、
プロパティ名は列名と同じにしてあります。

class USER_MASTER
{
    public string USER_ID { get; set; }
    public string DEPT_NO { get; set; }
    public string USER_NAME { get; set; }
    public DateTime? CREATED_ON { get; set; }
    public DateTime? MODIFIED_ON { get; set; }
}

Select

// 接続情報作成
using(var connection = DbProvider.CreateConnection(DbKind.Oracle, ConfigurationManager.ConnectionStrings[connectionName].ConnectionString))
{
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            // SQL文無しでSelect
            var rowsNonSQL = transaction.Select<USER_MASTER>(col => col.USER_ID == "0001");
            // SQL文有りでSelect
            var sql = @"SELECT * FROM USER_MASTER WHERE USER_ID = :USER_ID";
            var bindObj = new USER_MASTER() { USER_ID = "0001" };
            var rowsSQL = transaction.Query<USER_MASTER>(sql, bindObj);
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Insert

// 接続情報作成
using (var connection = DbProvider.CreateConnection(DbKind.Oracle, ConfigurationManager.ConnectionStrings[connectionName].ConnectionString))
{
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            try
            {
                // SQL文無しでInsert
                // Insert用インスタンス作成
                var insertObjNonSQL = new USER_MASTER() { USER_ID = "9999", DEPT_NO = "9999" };
                // Insert
                var resultNonSQL = transaction.Insert(insertObjNonSQL);

                // SQL文でInsert
                // SQL文作成
                var sql = @"INSERT INTO USER_MASTER ( USER_ID, DEPT_NO ) VALUES ( :USER_ID, :DEPT_NO )";
                // Insert用インスタンス作成
                var insertObjSQL = new USER_MASTER() { USER_ID = "8888", DEPT_NO = "8888" };
                // Insert実行
                var resultSQL = transaction.Execute(sql, insertObjSQL);

                // コミット
                transaction.Commit();
            }
            catch
            {
                // ロールバック
                transaction.Rollback();
                throw;
            }
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Update

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでUpdate
// Update用インスタンス作成
var updateObjNonSQL = new USER_MASTER() { USER_ID = "9999", USER_NAME = "HOGE" };
// Update
var resultNonSQL = transaction.Update(updateObjNonSQL, col => col.USER_ID == updateObjNonSQL.USER_ID);

// SQL文でUpdate
// SQL文作成
var sql = @"UPDATE USER_MASTER SET USER_NAME = :USER_NAME WHERE USER_ID = :USER_ID";
// Update用インスタンス作成
var updateObjSQL = new USER_MASTER() { USER_ID = "8888", USER_NAME = "FUGA" };
// Update実行
var resultSQL = transaction.Execute(sql, updateObjSQL);
// コネクションやトランザクション関係の後処理(省略)

Delete

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでDelete
// Delete
var resultNonSQL = transaction.Delete<USER_MASTER>(col => col.USER_ID == "9999");

// SQL文でDelete
// SQL文作成
var sql = @"DELETE FROM USER_MASTER WHERE USER_ID = :USER_ID";
// Delete用インスタンス作成
var DeleteObjSQL = new USER_MASTER() { USER_ID = "8888" };
// Delete実行
var resultSQL = transaction.Execute(sql, DeleteObjSQL);
// コネクションやトランザクション関係の後処理(省略)


DeclarativeSqlもDapperと同じくコネクション作成やらトランザクション開始やらの
お決まりのコードをどうにかしてやりたい感じですね。
でも、コネクション作成の作業が簡略化されていたり、
簡単な操作ならSQL文を書かなくても良かったり、利便性は確実に上がっています!
これは業務でも使いたいですね。
(今はすべてSQLを書いている。)

Dapperを触ってみた(導入、簡単な操作編)(Micro-ORM)

簡単にDBを操作できるライブラリを探している中で、
Dapperを見つけ触ってみたので、記事として残しておきます。

用途としては、EntityFrameworkと併用することが多いみたいですね。
EntityFrameworkでいけるところはEntityFrameworkを使用し、
手の届かない痒いところはDapperで対応する。といった感じでしょうか。
あ、サンプルの言語はC#です。

お品書き

Dapperとは

以下URLに載っていることを読んでください。(丸投げ)
GitHub - StackExchange/Dapper: Dapper - a simple object mapper for .Net

インストール方法

以下のコマンドをパッケージマネージャコンソールで実行するだけです。
簡単!

Install-Package Dapper

簡単な操作方法

コネクション作って、App.configの情報を元に接続して、
トランザクション開始して、各操作を行い、
最後に接続を切断しています。
Insert、Update、Deleteは、上記以外にコミット、ロールバックを行っていますね。
例外が発生しなければコミット、
例外が発生したらロールバックという実装にしています。

使用しているEntityクラス

クラス名はテーブル名と同じ、
プロパティ名は列名と同じにしてあります。

class USER_MASTER
{
    public string USER_ID { get; set; }
    public string DEPT_NO { get; set; }
    public string USER_NAME { get; set; }
    public DateTime? CREATED_ON { get; set; }
    public DateTime? MODIFIED_ON { get; set; }

    // プロパティの値確認用
    public override string ToString()
    {
        var retStr = new StringBuilder();
        retStr.AppendFormat("USER_ID:{0}\t", this.USER_ID);
        retStr.AppendFormat("DEPT_NO:{0}\t", this.DEPT_NO);
        retStr.AppendFormat("USER_NAME:{0}\t", this.USER_NAME);
        retStr.AppendFormat("CREATED_ON:{0}\t", this.CREATED_ON);
        retStr.AppendFormat("MODIFIED_ON:{0}\t", this.MODIFIED_ON);
        return retStr.ToString();
    }
}

Select

// プロバイダの情報を取得
var provider = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings[connectionName].ProviderName);
// 接続情報取得
using (var connection = provider.CreateConnection())
{
    // 接続文字列をApp.configから取得し設定
    connection.ConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            // Select文作成
            var sql = @"SELECT * FROM USER_MASTER WHERE USER_ID = :USER_ID";
            // バインド変数用インスタンス作成
            var bindObj = new USER_MASTER() { USER_ID = "0001" };
            // Select文実行
            var rows = connection.Query<USER_MASTER>(sql, bindObj, transaction);
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Insert

// プロバイダの情報を取得
var provider = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings[connectionName].ProviderName);
// 接続情報取得
using (var connection = provider.CreateConnection())
{
    // 接続文字列をApp.configから取得し設定
    connection.ConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            try
            {
                // Insert文作成
                var sql = @"INSERT INTO USER_MASTER ( USER_ID, DEPT_NO ) VALUES ( :USER_ID, :DEPT_NO )";
                // Insert用インスタンス作成
                var insertObj = new USER_MASTER() { USER_ID = "9999", DEPT_NO = "9999" };
                // Insert文実行
                var result = connection.Execute(sql, insertObj, transaction);
                // コミット
                transaction.Commit();
            }
            catch
            {
                // ロールバック
                transaction.Rollback();
                throw;
            }
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Update

接続やトランザクション周りはInsertと同じなので割愛。

// コネクションやトランザクション関係の前処理(省略)
// Update文作成
var sql = @"UPDATE USER_MASTER SET USER_NAME = :USER_NAME WHERE USER_ID = :USER_ID";
// Update用インスタンス作成
var updateObj = new USER_MASTER() { USER_ID = "9999", USER_NAME = "HOGE" };
// Update文実行
var result = connection.Execute(sql, updateObj, transaction);
// コネクションやトランザクション関係の後処理(省略)

Delete

// コネクションやトランザクション関係の前処理(省略)
// Update文作成
var sql = @"DELETE FROM USER_MASTER WHERE USER_ID = :USER_ID";
// Delete用インスタンス作成
var deleteObj = new USER_MASTER() { USER_ID = "9999"};
// Update文実行
var result = connection.Execute(sql, deleteObj, transaction);
// コネクションやトランザクション関係の後処理(省略)


各DBに依存せず使用できそうですし、簡単に使用できて良いですね。
でも、毎回コネクションやトランザクション関係のお決まりとなっているコードを
書くのは非常につらいので、これらはフレームワーク化(ライブラリ化)し、
隠蔽してやる必要がありそうです。