まず点字についての基本を述べておきます。
点字は1マス6点(縦3x横2)で表現します。50音はそれで間に合いますが、濁音・半濁音・拗音その他特殊音などを含めると6マスの組み合わせでは足りなくなります。そういう音には2マスを使って表現します。
1マス目がどの音なのかと言う表示で2マス目はそれを使って表現したい50音となります。例えば1マス目が濁音の印で2マス目が「か」を表すとすれば「が」という文字を表現します。
また、点字を打つ道具を点字器と呼びますが、それは一般的に1行32マス、1ページ18行です。
表ページの行間は縦1マス分ちょっとあり、裏ページの行に使います。つまり表裏で点字を36行打つことが出来ます。
前回作成したものは点字データを Excel に保残していましたが、Visual C# から Excel のアクセス速度が遅いためデータベースを使うことにしました。
使用するのは Entity Data Model のタイプです。
このタイプのデータベースは今まで全く使ったことがなかったので、書籍を買って読んだりネット検索して調べたりしてようやく使い方が分かってきたところです。データセットなどは使わないで直接データベースと読み書きしているように見えます。また SQL 文をプログラム内で自由にコーディングできるので前もって準備しておく必要がありません。データベースにアクセスするのに必要なものは接続文字列が必ず要ります。また更新系の場合ではデータベースのエンティティ名も必要です。このエンティティと言うものが分からなくて困惑していました。直訳すると「実態」などと言う意味です。
簡単に言ってしまうとここで使うデータベースの実態を表現しているものとかなのでしょう。
ここから、作成したVisual C# のプログラム説明です。
最初に開く画面1で全部の点字データが DataGridView に検索表示されます。ここで一行だけ選択してブルーにします。それから、点字変換または墨字変換へとボタンを押下することで画面が遷移します。
点字変換では、文字を入力してそれを点字へと変換し表示します。
- ここでの点字は Bitmap に描いておりその結果を PictureBox へ表示しています。そのため凸字と凹字の入れ替えは速くてあっという間です。
- 5マスおきに縦線を入れてマス目をわかりやすくするように工夫しました。
- 点字では「、」の後ろは1つの空白、「。」の後ろは2つの空白を開けますのでそのチェックをしています。
- 点字では「こんにちは」は「こんにちわ」などと言う通りに表現しますのでそういったチェックを入れています。
- 1行32マスに収まらない場合もチェックしています。
- これらのチェック結果も Bitmap で表現して PictureBox に表示しています。
墨字変換では、点字を入力してそれを文字へと変換し表示します。
- 点字を入力するのには32マスx18行を6点表示しています。点の数は全部で 3,456 個です。
- これらは CheckBox でプログラム内で動的に作成しています。
- 凸字と凹字の変換はチェックしてある点を保存してから、一旦すべての CheckBox を削除・Dispose します。左右逆に CheckBox を作り直して保存しておいたチェックの場所には新たにチェックを入れます。そのために PC の性能にもよるとは思いますが私のものでは16秒前後かかりました。これを速くしようと色々と試してました。格段に良くなったのは、書き換える間は画面を非表示(Visible=false;)にすることです。終わったら表示(Visible=true;)します。これで6秒程度にまで速くなりました。
この両方のプログラムで変換結果の内容を見比べてみて、違いが無ければ正しい変換がされているという事が分かります。
私の場合、文字から点字への変換でページ番号を自動で追加する機能があるのですが、それが前の空白を半角で入力しているというバグが分かりました。全角でないと駄目ですね。
データベースの実体は予め作成しておく必要があります。
[プロジェクト] [新規項目の追加] [データ] [サービスベースのデータベース]
でデータベースの実態を作ります。
次にテーブルの作成をします。
テーブルを右クリックして [新規テーブルの作成]を選択します。
テーブル作成画面が出ますのでテーブル名を適当なものに変更してから、列を追加していきます。
全部出来たら更新ボタンをクリックします。スクリプトが準備出来たら [データベースの更新] をクリックしてエラーがないことを確認します。
サーバーエクスプローラーを最新の情報に変更してからテーブルを確認します。作成したテーブルがあるはずです。
又、データ接続をするときにローカルにコピーを作りますかと言う質問では [No( 作らないを)]選択してください。そうしないとプログラムが終了するとともに変更したテーブルの内容が消えてしまいます。
そして[接続のテスト]を行いうまくゆくことを確認してください。
[プロジェクト] [新規項目の追加] [オンラインテンプレート] [ADO.NET Entity Data Model] とします。
空のエンティティが作られるのでそれにテーブルを追加します。そうしないと使えません。
Model1.edmx で右クリックして [テーブルからモデルを更新] を選びます。
更新ウィザードの [追加タブ] で先ほど作ったテーブルを選んでチェックを入れて[完了]します。
エンティティにテーブルが追加されました。
データベースへの接続文字列の探し方
使っているのは Entity Data Model のデータベースです。サーバーエクスプローラーで、データベースを右クリックしてプロパティを選びます。
ソリューションエクスプローラーの接続文字列と言う個所の右側に表示されます。一度クリックしてから [ctrl]+[c] でクリップボードにコピーしてプログラムの必要個所に [ctrl]+[v] で貼り付けます。
テーブルアクセス Class のサンプル1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormApplication1
{
class DBText
{
public static bool ReadTextDB_All(DataGridView dg1, string CS)
{
bool ans = false;
StringBuilder query = new StringBuilder();
query.AppendLine("SELECT");
query.AppendLine(" DocumentName");
query.AppendLine(" ,PageNo");
query.AppendLine(" ,PageText");
query.AppendLine("FROM");
query.AppendLine(" Tenji_Text");
//query.AppendLine("WHERE");
//query.AppendLine(" DocumentName = @Doc");
//query.AppendLine("AND PageNo = @Pag");
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
// SQLの設定
command.CommandText = query.ToString();
//command.Parameters.Add(new SqlParameter("@Doc", _doc));
//command.Parameters.Add(new SqlParameter("@Pag", _pg));
// SQLの実行
var adapter = new SqlDataAdapter(command);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
ans = true;
dg1.Rows.Add
(
reader["DocumentName"], reader["PageNo"].ToString(), reader["PageText"]
);
}
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return ans;
}
public static bool ReadTextDB_Select(DataGridView dg1, string _doc, int _pg, TextBox tbPgText, string CS)
{
bool ans = false;
StringBuilder query = new StringBuilder();
query.AppendLine("SELECT");
query.AppendLine(" DocumentName");
query.AppendLine(" ,PageNo");
query.AppendLine(" ,PageText");
query.AppendLine("FROM");
query.AppendLine(" Tenji_Text");
query.AppendLine("WHERE");
query.AppendLine(" DocumentName = @Doc");
query.AppendLine("AND PageNo = @Pag");
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
// SQLの設定
command.CommandText = query.ToString();
command.Parameters.Add(new SqlParameter("@Doc", _doc));
command.Parameters.Add(new SqlParameter("@Pag", _pg));
// SQLの実行
var adapter = new SqlDataAdapter(command);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
ans = true;
dg1.Rows.Add
(
reader["DocumentName"], reader["PageNo"].ToString(), reader["PageText"]
);
tbPgText.Text = reader["PageText"].ToString();
}
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return ans;
}
public static bool UpdateTextDB(Database1Entities _ent, string _doc, int _pg, string _txt, string CS)
{
bool ans = false;
StringBuilder query = new StringBuilder();
query.AppendLine("UPDATE");
query.AppendLine(" Tenji_Text");
query.AppendLine("SET PageText = ");
query.AppendLine(" @txt");
query.AppendLine("WHERE");
query.AppendLine(" DocumentName = @Doc");
query.AppendLine("AND PageNo = @Pag");
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
// SQLの設定
command.CommandText = query.ToString();
command.Parameters.Add(new SqlParameter("@txt", _txt));
command.Parameters.Add(new SqlParameter("@Doc", _doc));
command.Parameters.Add(new SqlParameter("@Pag", _pg));
// SQLの実行
var adapter = new SqlDataAdapter(command);
command.ExecuteNonQuery();
_ent.SaveChanges();
ans = true;
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return ans;
}
public static bool InsertTextDB(Database1Entities _ent, string _doc, int _pg, string _txt, string CS)
{
bool ans = false;
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
// SQLの準備
command.CommandText = @"INSERT INTO Tenji_Text (DocumentName, PageNo, PageText) VALUES (@Doc, @PgNo, @PgTxt)";
command.Parameters.Add(new SqlParameter("@Doc", _doc));
command.Parameters.Add(new SqlParameter("@PgNo", _pg));
command.Parameters.Add(new SqlParameter("@PgTxt", _txt));
// SQLの実行
command.ExecuteNonQuery();
_ent.SaveChanges();
ans = true;
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
ans = false;
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return ans;
}
}
}
select文では dataGridView をパラメータで渡してデータを追加しています。
呼び出し側の例
//接続定数
const string CS = @"Connection Strings";
// -----------
#region 次ページ ボタン処理
//次ページ ボタン処理
private void buttonNext_Click(object sender, EventArgs e)
{
labelMessage.Text = "";
int wpg = pageNo;
wpg++;
if (DBText.ReadTextDB_Select(dataGridView1, labelDocument.Text, wpg, textBoxMongon, CS))
{
pageNo++;
labelPage.Text = pageNo.ToString();
Tenyaku0();
labelMessage.Text = " 次のページが見つかりました。";
}
else
{
labelMessage.Text = " 次のページはありません。";
}
}
#endregion;
テーブルアクセス CLASS のサンプル2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormApplication1
{
class DBData
{
public static int GetDocPageLines(string _doc, int _pg, string CS)
{
int cnt = -1;
StringBuilder query = new StringBuilder();
//select count(*) from actor where first_name like 'N%';
query.AppendLine("SELECT");
query.AppendLine(" *");
query.AppendLine("FROM");
query.AppendLine(" Tenji_Data");
query.AppendLine("WHERE");
query.AppendLine(" DocumentName = @Doc");
query.AppendLine("AND PageNo = @Pag");
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
// SQLの設定
command.CommandText = query.ToString();
command.Parameters.Add(new SqlParameter("@Doc", _doc));
command.Parameters.Add(new SqlParameter("@Pag", _pg));
// SQLの実行
var adapter = new SqlDataAdapter(command);
using (SqlDataReader reader = command.ExecuteReader())
{
cnt = 0;
while (reader.Read())
{
cnt++;
}
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return cnt;
return cnt;
}
public static string ReadDatatDB_Select(string _doc, int _pg, int _lin, string CS)
{
string ans = "";
StringBuilder query = new StringBuilder();
query.AppendLine("SELECT");
query.AppendLine(" DocumentName");
query.AppendLine(" ,PageNo");
query.AppendLine(" ,PageTenji");
query.AppendLine("FROM");
query.AppendLine(" Tenji_Data");
query.AppendLine("WHERE");
query.AppendLine(" DocumentName = @Doc");
query.AppendLine("AND PageNo = @Pag");
query.AppendLine("AND [LineNo] = @Lin");
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
// SQLの設定
command.CommandText = query.ToString();
command.Parameters.Add(new SqlParameter("@Doc", _doc));
command.Parameters.Add(new SqlParameter("@Pag", _pg));
command.Parameters.Add(new SqlParameter("@Lin", _lin));
// SQLの実行
var adapter = new SqlDataAdapter(command);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
ans = reader["PageTenji"].ToString();
break;
}
}
}
catch (Exception exception)
{
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return ans;
}
public static bool UpdateDataDB(Database1Entities _ent, string _doc, int _pg, string _tnj, int _lin, string CS)
{
bool ans = false;
StringBuilder query = new StringBuilder();
query.AppendLine("UPDATE");
query.AppendLine(" Tenji_Data");
query.AppendLine("SET PageTenji = ");
query.AppendLine(" @Tnj");
query.AppendLine("WHERE");
query.AppendLine(" PageNo = @Pag ");
query.AppendLine("AND [LineNo] = @Lin ");
query.AppendLine("AND DocumentName = @Doc");
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
// SQLの設定
command.CommandText = query.ToString();
command.Parameters.Add(new SqlParameter("@Tnj", _tnj));
command.Parameters.Add(new SqlParameter("@Pag", _pg));
command.Parameters.Add(new SqlParameter("@Lin", _lin));
command.Parameters.Add(new SqlParameter("@Doc", _doc));
// SQLの実行
var adapter = new SqlDataAdapter(command);
command.ExecuteNonQuery();
_ent.SaveChanges();
ans = true;
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return ans;
}
public static bool InsertDatatDB(Database1Entities _ent, string _doc, int _pg, int _lin, string _tnj, string CS)
{
bool ans = false;
// SQLの準備
StringBuilder query = new StringBuilder();
query.AppendLine("INSERT INTO Tenji_Data ");
query.AppendLine(" ( DocumentName, ");
query.AppendLine(" PageNo, ");
query.AppendLine(" [LineNo], ");
query.AppendLine(" PageTenji)");
query.AppendLine(" VALUES " );
query.AppendLine(" (@DocumentName,");
query.AppendLine(" @PageNo,");
query.AppendLine(" @LineNo,");
query.AppendLine(" @PageTenji) ");
// 接続文字列の取得
var connectionString = CS;
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
command.CommandText = query.ToString();
command.Parameters.Add(new SqlParameter("@DocumentName", _doc));
command.Parameters.Add(new SqlParameter("@PageNo", _pg));
command.Parameters.Add(new SqlParameter("@LineNo", _lin));
command.Parameters.Add(new SqlParameter("@PageTenji", _tnj));
// SQLの実行
command.ExecuteNonQuery();
_ent.SaveChanges();
ans = true;
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
ans = false;
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
return ans;
}
}
}
呼び出し側の例
//接続定数
const string CS = @"Connection Strings";
// -----------
#region DB 書込み ボタン処理
private void buttonUpdateDB_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("[墨字 変換]しましたか。本当にこの結果をデータベースに反映しますか。", "[DB 更新]ボタンの確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
convertFromTenjiToData();
try
{
DBText.UpdateTextDB(_ent, labelDocument.Text, pageNo, textBoxMongon.Text, CS);
for (int i = 1; i <= LinesPerPage; i++)
{
DBData.UpdateDataDB(_ent, labelDocument.Text, pageNo, Data[i - 1], i, CS);
}
labelMessage.Text = "[DB 更新] が正しく済みました。";
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
#endregion;
列名 LineNo 「この場所の近辺で構文エラーがあります」と言う SQL のエラーが出て理由が全然分かりませんでした。試しにと思って列名を [LineNo] のように括弧でくくってみたら正解でした。 SQLがうまく動きました。これを解決するのにかかった時間(8時間くらい)を返してもらいたいです。どうも LineNo 言うのは予約済みキーワードという事で、でそれを列名に指定したからエラーだというわけでした。