SQLの窓

2019年03月19日


C# : SQL 文を外部テキストにして、String.Format でデータ部分を置き換えて利用する

基本的には、String.Format メソッドのお話ですが、文字列の配列の扱いとの関係での注意事項です。
-- ******************************
-- 社員マスタ更新
-- ******************************
 
UPDATE 社員マスタ
set
氏名 = '{1}',
給与 = {2},
-- 行コメント
生年月日 = {3}

--
 
where 社員コード = '{0}'
 
-- 行コメント
行コメントは、正規表現で削除します。{} 部分の個数より、配列が大きい必要があり、Nothing が指定されると、{} ごとなくなります。
※ 配列のリサイズが必要な場合は、Array.Resize メソッドで行います。


C# による記述
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace text_input
{
	class Program
	{
		static void Main(string[] args)
		{
			// 入力ファイルのパス
			string[] arguments = Environment.GetCommandLineArgs();
			// 引数は一つのみ許可
			if (arguments.Length != 2)
			{
				Console.WriteLine("引数を指定して下さい");
				return;
			}

			// 引数から取得
			string filePath = arguments[1];

			// パスを表示
			Console.WriteLine(filePath);

			// *********************************
			// ▼ 関数呼び出しを記述して、ALT + Enter で自動作成
			// *********************************
			string textData = loadTextData(filePath);

			// *********************************
			// 行コメントの削除
			// ▼ 正規表現のオプション
			// https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/regular-expression-options
			// *********************************
			string pattern = "(?m)^--.*";   // 複数行モード
			textData = System.Text.RegularExpressions.Regex.Replace(textData, pattern, "");

			Console.Write(textData);

			// *********************************
			// 配列の準備(1)
			// *********************************
			string[] data1 = { "0001", "山田太郎", "100000", "'1980/01/01'" };
			Console.WriteLine("配列の数は {0} です", data1.Length);

			// *********************************
			// 配列を文字列内に埋め込む
			// *********************************
			string sqlResult = String.Format(textData, data1);
			Console.Write(sqlResult);

			// *********************************
			// 配列の準備(2)
			// *********************************
			string[] data2 = new string[4];
			data2[0] = "0002";
			data2[1] = "山田花子";
			data2[2] = "20000";
			data2[3] = "NULL";

			// *********************************
			// 配列を文字列内に埋め込む
			// *********************************
			sqlResult = String.Format(textData, data2);
			Console.Write(sqlResult);

			// *********************************
			// 配列の準備(3)
			// *********************************
			string[] data3 = new string[4];
			data3.SetValue("0003", 0);
			data3.SetValue("山田美子", 1);
			data3.SetValue("30000", 2);
			data3.SetValue("'1980/01/01'", 3);

			// *********************************
			// 配列を文字列内に埋め込む
			// *********************************
			sqlResult = String.Format(textData, data3);
			Console.Write(sqlResult);

			// *********************************
			// 配列の準備(4)
			// *********************************
			List<string> data4 = new List<string>();
			data4.Add("0004");
			data4.Add("山田史郎");
			data4.Add("40000");
			data4.Add("'1990/01/01'");

			// *********************************
			// 配列を文字列内に埋め込む
			// *********************************
			sqlResult = String.Format(textData, data4.ToArray());
			Console.Write(sqlResult);

			// *********************************
			// 配列の準備(5)
			// ※ 追加するデータ型自由
			// *********************************
			ArrayList data5 = new ArrayList();
			data5.Add("0005");
			data5.Add("山田吾郎");
			data5.Add(50000);
			data5.Add(new DateTime(1995, 1, 1));

			// *********************************
			// 配列を文字列内に埋め込む
			// 混在なので object 配列
			// *********************************
			object[] strWork = data5.ToArray();
			sqlResult = String.Format(textData, strWork[0], strWork[1], strWork[2], $"'{strWork[3]}'");
			Console.Write(sqlResult);

			Console.ReadLine();

		}

		private static string loadTextData(string filePath)
		{

			string text = "";

			// *********************************
			// 主なエンコード
			// *********************************
			// SHIFT_JIS
			// Encoding Enc = Encoding.GetEncoding(932);
			// EUC-JP
			//Encoding Enc = Encoding.GetEncoding(51932);
			// UNICODE 用
			//Encoding Enc = Encoding.GetEncoding(1200);
			// UTF-8N
			Encoding Enc = new UTF8Encoding();
			// UTF-8
			//Encoding Enc = new UTF8Encoding(true);

			// プロック終了時に開放
			try
			{
				using (StreamReader ReadFile = new StreamReader(filePath, Enc))
				{
					// 読込み
					text = ReadFile.ReadToEnd();

					// 全て読み込んでいるので閉じる
					ReadFile.Close();

					Console.Write(text);
				}

			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}

			return text;

		}
	}
}

引数は、プロジェクトのプロパティからデバッグタブを開けて設定します。





posted by lightbox at 2019-03-19 09:48 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2019年03月13日


C# コンソールアプリを AN HTTPD で実行

テストにはまだまだ使える(重宝する) AN HTTP Server の正しい使用方法

単純に、WEB アプリケーション初心者にブラウザとサーバーのやり取りを知ってもらう為に( 今は、開発者ツールがあるので途中の解説がしやすいですし )、C# で作った EXE をそのままブラウザで実行させます。

基本設定

EXE の列の『一般パスでも実行する』にチェックします



次に、一般パスに C# で作成された Debug フォルダを登録します。



後は、loclhost から実行するだけです。

ソースコード
using System;
using System.Collections;
using System.Text;
using System.Web;

namespace cgi_test
{
	class Program
	{
		static void Main(string[] args)
		{
			string formtype = "POST";

			string[] param = { };

			// ******************************
			// Console.WriteLine を UTF8 で
			// ******************************
			Console.OutputEncoding = Encoding.UTF8;

			// ******************************
			// メソッド
			// ******************************
			string method = Environment.GetEnvironmentVariable("REQUEST_METHOD");

			// ******************************
			// GET
			// ******************************
			if (method == "GET")
			{
				// ******************************
				// QUERY_STRING
				// ******************************
				string query_string = System.Environment.GetEnvironmentVariable("QUERY_STRING");
				// URL のみの場合はデータ無しの QUERY_STRING を用意する
				if (query_string == "" )
				{
					query_string = "field1=&field2=";
				}

				// & で分割して key=value の文字列の配列を作成する
				param = query_string.Split('&');
			}

			// ******************************
			// POST
			// ******************************
			if (method == "POST")
			{
				string line;

				// POST 時は必ず key=value の文字列が存在する
				line = Console.ReadLine();
				param = line.Split('&');
			}

			// = で区切って key と value が配列の 0 と 1 にセットされる
			string[] key_value = { };

			// ******************************
			// key と value の格納
			// ******************************
			Hashtable field = new Hashtable();

			foreach (string key_value_set in param)
			{
				key_value = key_value_set.Split('=');
				// key がある場合は、Hashtable に格納する
				if (key_value[0] != "") {
					// System.Web を参照して using System.Web; で HttpUtility.UrlDecode
					// %エンコードを元に戻す
					field.Add(key_value[0], HttpUtility.UrlDecode(key_value[1]));
				}
			}

			// ******************************
			// HTTP ヘッダ
			// PHP の session_cache_limiter
			// ******************************
			Console.WriteLine("Content-Type: text/html; charset=utf-8");
			Console.WriteLine("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
			Console.WriteLine("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
			Console.WriteLine("Pragma: no-cache");
			Console.WriteLine();

			string message = "<div>こんにちは世界</div>";

			// ******************************
			// HTML
			// $ で変数埋め込みのヒアドキュメント
			// ******************************
			string html = $@"<!DOCTYPE html>
<html>
<head>
</head>
<body>
{message}
<form method='{formtype}'>
<p>氏名 : <input type='text' name='field1' value='{field["field1"]}'></p>
<p>フリガナ : <input type='text' name='field2' value='{field["field2"]}'></p>
<p>送信 : <input type='submit' name='send' value='送信'></p>
</form>
</body>
</html>";

			// 作成した HTML を出力する
			Console.WriteLine(html);
		}
	}
}





posted by lightbox at 2019-03-13 22:02 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2019年03月07日


VBScript : 複数テキストファイルの charset(キャラクタセット) 一括変換 / ADODB.Stream

ADODB.Stream を使用すると、テキストファイルのキャラクタセットををメモリ内で変換する事ができます

※ 変換元と変換後のキャラクタセットを指定する必要があります
※ ここでの対象ディレクトリはカレントにある "res" ディレクトリです
※ SaveToFile オプションの 2 は 上書きを意味します

utf8(BOMあり) または utf8n より shift_jis
'****************************************
' utf8(BOMあり) または utf8n より shift_jis
'****************************************

Set Fso = CreateObject( "Scripting.FileSystemObject" )
Set Stream1 = CreateObject("ADODB.Stream")
Set Stream2 = CreateObject("ADODB.Stream")

Set objFolder = Fso.GetFolder( "res" )
Set objFiles = objFolder.Files

For each objFile in objFiles
	' フルパス
	strFullPath = Fso.GetAbsolutePathName( "res\" & objFile.Name )

	' utf-8 として開く( utf8 でも utf8n でも OK )
	Stream1.Open
	Stream1.Type = 2	' StreamTypeEnum の adTypeText(デフォルト)
	Stream1.Charset = "utf-8"

	' utf-8 として読み込む
	Stream1.LoadFromFile strFullPath

	' shift_jis として開く
	Stream2.Open
	Stream2.Type = 2
	Stream2.Charset = "shift_jis"

	' utf-8 から shift_jis に変換コピーする
	Stream1.CopyTo Stream2
	Stream2.SaveToFile strFullPath, 2	' 上書き保存

	' ストリームを閉じる
	Stream2.Close
	Stream1.Close

Next

MsgBox("処理が終了しました")


shift_jis から utf8( BOMあり )
'****************************************
' shift_jis から utf8( BOMあり )
'****************************************
Set Fso = CreateObject( "Scripting.FileSystemObject" )
Set Stream1 = CreateObject("ADODB.Stream")
Set Stream2 = CreateObject("ADODB.Stream")

Set objFolder = Fso.GetFolder( "res" )
Set objFiles = objFolder.Files

For each objFile in objFiles
	' フルパス
	strFullPath = Fso.GetAbsolutePathName( "res\" & objFile.Name )

	' shift_jis として開く
	Stream1.Open
	Stream1.Type = 2	' StreamTypeEnum の adTypeText(デフォルト)
	Stream1.Charset = "shift_jis"

	' shift_jis として読み込む
	Stream1.LoadFromFile strFullPath

	' utf-8 として開く
	Stream2.Open
	Stream2.Type = 2
	Stream2.Charset = "utf-8"

	' shift_jis から utf-8 に変換コピーする
	Stream1.CopyTo Stream2
	Stream2.SaveToFile strFullPath, 2	' 上書き保存

	' ストリームを閉じる
	Stream2.Close
	Stream1.Close

Next

MsgBox("処理が終了しました")


shift_jis から utf8n( BOMなし )

BOM ありは作成できるので、バイナリモードを使用して先頭3バイトを取り去る処理を追加しています
'****************************************
' shift_jis から utf8n( BOMなし )
'****************************************

Set Fso = CreateObject( "Scripting.FileSystemObject" )
Set Stream1 = CreateObject("ADODB.Stream")
Set Stream2 = CreateObject("ADODB.Stream")
Set Stream3 = CreateObject("ADODB.Stream")

Set objFolder = Fso.GetFolder( "res" )
Set objFiles = objFolder.Files

For each objFile in objFiles
	' フルパス
	strFullPath = Fso.GetAbsolutePathName( "res\" & objFile.Name )

	' shift_jis として開く
	Stream1.Open
	Stream1.Type = 2	' StreamTypeEnum の adTypeText(デフォルト)
	Stream1.Charset = "shift_jis"

	' shift_jis として読み込む
	Stream1.LoadFromFile strFullPath

	' utf-8 として開く
	Stream2.Open
	Stream2.Type = 2
	Stream2.Charset = "utf-8"

	' shift_jis から utf-8 に変換コピーする
	Stream1.CopyTo Stream2

	' ストリームを閉じる
	Stream1.Close

	' 開始位置を先頭にして、バイナリの扱いに変更
	Stream2.Position = 0
	Stream2.Type = 1

	' BOM なしをコピーするバイナリストリーム
	Stream3.Open
	Stream3.Type = 1

	' 先頭3バイトを読み飛ばし
	Stream2.Read(3)

	' 先頭3バイトを省いてコピー
	Stream2.CopyTo Stream3

	' UTF8N で保存
	Stream3.SaveToFile strFullPath, 2	' 上書き保存

	' ストリームを閉じる
	Stream3.Close
	Stream2.Close

Next

MsgBox("処理が終了しました")

Stream オブジェクト
Type プロパティ






タグ:VBScript charset VBS
posted by lightbox at 2019-03-07 14:51 | VBS + オブジェクト | このブログの読者になる | 更新情報をチェックする

空の zip ファイル / VBScript で作成可能

「新規作成」は、レジストリに登録されています

フォルダ内で、右クリックすると表示されるポップアップメニューには「新規作成」というメニューがありますが、これは、Windows Shell 仕様に従ってレジストリに登録された情報を元に作成されています。



この中で「圧縮 (zip形式) フォルダ」とあるメニューを実行すると、空の zip ファイルが作成されます。これをダンプすると以下のような内容になっています
          0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
--------------------------------------------------------------------------
00000000 50 4B 05 06 00 00 00 00 00 00 00 00 00 00 00 00  PK..............
00000010 00 00 00 00 00 00                                ......

504B0506
0000     ディスク情報1
0000     ディスク情報2
0000     エントリされたデータの情報1
0000     エントリされたデータの情報2
00000000 サイズ情報
00000000 データへのオフセット
0000     後続するコメントの長さ
結構単純なデータですが、これは以下のようなレジストリデータとして直接データが登録されています。

コンピューター\HKEY_CLASSES_ROOT\.zip\CompressedFolder\ShellNew


Data という名前で登録されているデータが作成されるようになっています。この仕様はこちら(英文)から確認できます

さらに、この空のzip書庫は、以下のようにしてスクリプトで作成する事もできます
Set Fso = CreateObject( "Scripting.FileSystemObject" )
Set Handle = Fso.CreateTextFile( "empty.zip", True )
EmptyData = Chr(&H50) & Chr(&H4B) & Chr(&H5) & Chr(&H6)
EmptyData = EmptyData & String( 18, Chr(0) )
Handle.Write EmptyData
Handle.Close


関連する情報

.ZIP File Format Specification( 仕様 )




タグ:書庫
posted by lightbox at 2019-03-07 13:22 | Windows | このブログの読者になる | 更新情報をチェックする

2019年03月02日


VBScript : 既存の Excel を PDF に変換する ( ExportAsFixedFormat )



単純な一覧データを出力した PDF の見本


2017/12/25 更新
Excel.Application を取得しているので、GetOpenFilename でファイルを選択できるようにしました。細かい詳細はソースコードにコメントに書き込んでいます

※ PDF は、Excel と同じ名前で拡張子を .pdf にしてスクリプトと同じフォルダに保存されます。
Excel 2007以降の Excelで名前を付けて保存で PDF に保存できますが、これはスクリプトで行うコードです。Excel 2007 を調べているとメソッド紹介されていたので、引数見た限り、 VBScriptでも動くだろうと試してみました。 ( プリンタが使える状態でないと動作しません ) ExportAsFixedFormat メソッド XlFixedFormatType 最近は、VBScript の単純コードである .vbs は Google Chrome での扱いが悪いので、.wsf で作成しています。もともと、.wsf のほうが簡単に外部ライブラリを参照したり、オブジェクトを最初から定義できるのでコードが簡潔になります。ここでは、Excel.Application 内で定義されている定数も参照して使えるようにしています。 Excel 側では、印刷設定により一行目のタイトルを常に表示するようにしたり、A4 横にして縮小したりしています。シートは二つありますが、PDF に変換すると全て出力されます。
<JOB>
<OBJECT id="Fso" progid="Scripting.FileSystemObject" />
<OBJECT id="ExcelApp" progid="Excel.Application" />
<REFERENCE guid="00020813-0000-0000-C000-000000000046" />
<SCRIPT language="VBScript">
' Wscript.Echo xlTypePDF,xlTypeXPS

' **************************************
' スクリプトのあるディレクトリの取得
' **************************************
strCurPath = WScript.ScriptFullName
Set obj = Fso.GetFile( strCurPath )
Set obj = obj.ParentFolder
strCurPath = obj.Path

' 途中で異常終了すると、Excel がプロセスに残ってしまうので表示させています。
' マウス等で Excel 本体を操作しないで下さい。
' Excel を表示させたくない場合は、以下を削除または行頭に ' でコメントにして下さい
ExcelApp.Visible = True

Dim MyBook
Dim FilePath

' ここで Excel を参照するダイアログが開きます
FilePath = ExcelApp.GetOpenFilename("Excel ファイル (*.xlsx;*.xls), *.xlsx;*.xls", 1, "Excel ファイルの選択") 
if FilePath = "False" Then 
	MsgBox "Excel ファイルの選択がキャンセルされました"
	' スクリプト終了
	Wscript.Quit()
End If

' ここで Excel に読み込んでいます
on error resume next
' Workbook を取得( スクリプトと同じディレクトリ )
Set MyBook = ExcelApp.Workbooks.Open( FilePath )
if Err.Number <> 0 then
	' 終了( 開放 )
	ExcelApp.Quit()
	Wscript.Echo Err.Description & vbCrLf & FilePath
	' スクリプト終了
	Wscript.Quit()
end if
on error goto 0

Dim aPath
Dim strFileName
Dim aExt

' Excel の名前部分を取り出して、pdf の名前部分にします
aPath = Split(FilePath, "\")
strFileName = aPath(Ubound(aPath))
aExt = Split(strFileName,".")
strFileName = aExt(0)

' スクリプトと同じフォルダに保存されます
Call MyBook.ExportAsFixedFormat( xlTypePDF, strCurPath & "\" & strFileName & ".pdf" )

' 終了( 開放 )
ExcelApp.Quit()

' 終了確認
Wscript.Echo "処理が終了しました"

</SCRIPT>
</JOB>


Microsoft の記事

Application.GetOpenFilename メソッド

Microsoft の英文の記事

Saving Workbooks to PDF and XPS Formats in Excel 2007




タグ:VBScript EXCEL PDF
posted by lightbox at 2019-03-02 17:39 | VBS + オブジェクト | このブログの読者になる | 更新情報をチェックする

JavaScript の内部コード文字列を SHIFT_JIS としてダウンロードさせる方法

SyntaxHighlighter カスタマイズ

SyntaxHighlighter のツールバーの右端のアイコンでファイルをダウンロードさせると、テキストのキャラクタセットは UTF-8 になります。通常はそれでもいいのですが、VBScript をダウンロードしてもらう場合は SHIFT_JIS である必要があるので、なんとかならないかと調べてみてすぐ見つけたのが

javascriptで文字コード変換

という Qiita の記事でした。その中で紹介されている ecl.js は、自分も以前使った事があったのですが、バイナリデータとして変換する目的では無いと記憶していました。ですが、一応記事の冒頭にあるコードでテストしてみましたがうまく行かず、Encoding.js のほうを使用して目的を達成しました。

Encoding.js

元々、バイナリの配列にデータを格納して変換しているので、文字列からの変換処理さえあればすぐ使えます。その関数は、Qiita の記事に既に紹介されていたのでとても簡単に実装する事ができました。

実装では、改行コードの扱いに留意して下さい。

サンプルコード
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js"></script>
<script src="https://winofsql.jp/js/encoding.js"></script>
<script src="https://winofsql.jp/js/save-sjis.js"></script>

<script>
$( function(){

	$("#save-action").on("click", function(){

		// テキストエリアのテキストを jQuery で取得		
		var text = $("#save-text").val();
		// lf のみを crlf に変換
		text = text.replace(/\n/g, '\r\n');
		// ローカルに保存する
		save_sjis( "save-sjis.txt", text );
	});

});
</script>
<div><input type="button" id="save-action" value="Save as Shift_JIS"></div>
<textarea id="save-text" style='width:400px;height:100px;'></textarea>


▼ save-sjis.js
var str2array = function(str) {

	var array = [],i,il=str.length;
	for(i=0;i<il;i++) array.push(str.charCodeAt(i));
	return array;

};

function save_sjis( filename, str ) {

	var array = str2array( str );
	var sjis_array = Encoding.convert(array, "SJIS", "UNICODE");
	var sjis_data = new Uint8Array(sjis_array);

	saveAs(
		new Blob(
			[sjis_data]
			, {type: "text/plain;charset=shift_jis"}
		)
		, filename
	);

}


▼ こちらでテストして下さい
( サンプルコードのソースを copy ボタンでコピーしてリンク先で貼り付けて実行して下さい)

関連する記事

ブラウザ上のテキストデータを名前を付けて保存できる FileSaver.js を使って、テーブルのデータを Excel で開ける事を想定した CSV にして PC に保存

ファイルを JavaScript から保存する FileSaver.js

FileSaver.js は saveAs メソッドを提供します。ダウンロードする必要は無く、cdnjs でホスティング されています。

Uint8Array


posted by lightbox at 2019-03-02 13:40 | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり