SQLの窓

2020年05月11日


MySQL : DB のデータを簡単に沢山作る方法は inner join

ページ処理のテストを行う為に、元を 7 件として、56 件のデータに増やす方法です。それぞれの SQL は、RDBMS 毎に動作するように書き換えれば実行可能です。

元のテーブル

既に 7 件のテストデータがあり、phpMyAdmin でエクスポートしています。phpMyAdmin はたいていのレンタルサーバで用意されていると思いますし、XAMPP をインストールして Windows のローカルでも利用可能です。
CREATE TABLE IF NOT EXISTS `board` (
  `row_no` serial,
  `body` varchar(1000),
  `subject` varchar(200),
  `from` varchar(20),
  `pdate` datetime,
  `cdate` datetime,
  primary key(`row_no`)
)

※ row_no は自動採番列です

データ

以下はエクスポートしたデータです。
-- phpMyAdmin SQL Dump
-- version 4.9.2
-- https://www.phpmyadmin.net/
--
-- ホスト: 127.0.0.1
-- 生成日時: 
-- サーバのバージョン: 10.4.10-MariaDB
-- PHP のバージョン: 7.3.12

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- データベース: `lightbox`
--

-- --------------------------------------------------------

--
-- テーブルの構造 `board`
--

CREATE TABLE `board` (
  `row_no` bigint(20) UNSIGNED NOT NULL,
  `body` varchar(1000) DEFAULT NULL,
  `subject` varchar(200) DEFAULT NULL,
  `from` varchar(20) DEFAULT NULL,
  `pdate` datetime DEFAULT NULL,
  `cdate` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- テーブルのデータのダンプ `board`
--

INSERT INTO `board` (`row_no`, `body`, `subject`, `from`, `pdate`, `cdate`) VALUES
(1, 'ある日の事でございます。御釈迦様は極楽の蓮池のふちを、独りでぶらぶら御歩きになっていらっしゃいました。池の中に咲いている蓮の花は、みんな玉のようにまっ白で、そのまん中にある金色の蕊からは、何とも云えない好い匂が、絶間なくあたりへ溢れて居ります。極楽は丁度朝なのでございましょう。\r\n', '蜘蛛の糸-1', '芥川龍之介-1', '2016-05-28 13:15:04', '2016-05-09 11:52:51'),
(2, 'やがて御釈迦様はその池のふちに御佇みになって、水の面を蔽っている蓮の葉の間から、ふと下の容子を御覧になりました。この極楽の蓮池の下は、丁度地獄の底に当って居りますから、水晶のような水を透き徹して、三途の河や針の山の景色が、丁度覗き眼鏡を見るように、はっきりと見えるのでございます。', '蜘蛛の糸-2', '芥川龍之介-2', '2016-05-28 13:22:37', '2016-05-14 20:07:14'),
(3, 'するとその地獄の底に、陀多と云う男が一人、ほかの罪人と一しょに蠢いている姿が、御眼に止まりました。この陀多と云う男は、人を殺したり家に火をつけたり、いろいろ悪事を働いた大泥坊でございますが、それでもたった一つ、善い事を致した覚えがございます。と申しますのは、ある時この男が深い林の中を通りますと、小さな蜘蛛が一匹、路ばたを這って行くのが見えました。そこで陀多は早速足を挙げて、踏み殺そうと致しましたが、「いや、いや、これも小さいながら、命のあるものに違いない。その命を無暗にとると云う事は、いくら何でも可哀そうだ。」と、こう急に思い返して、とうとうその蜘蛛を殺さずに助けてやったからでございます。', '蜘蛛の糸-3', '芥川龍之介-3', '2016-05-28 13:18:36', '2016-05-14 20:08:07'),
(4, '御釈迦様は地獄の容子を御覧になりながら、この陀多には蜘蛛を助けた事があるのを御思い出しになりました。そうしてそれだけの善い事をした報には、出来るなら、この男を地獄から救い出してやろうと御考えになりました。幸い、側を見ますと、翡翠のような色をした蓮の葉の上に、極楽の蜘蛛が一匹、美しい銀色の糸をかけて居ります。御釈迦様はその蜘蛛の糸をそっと御手に御取りになって、玉のような白蓮の間から、遥か下にある地獄の底へ、まっすぐにそれを御下しなさいました。', '蜘蛛の糸-4', '芥川龍之介-4', '2016-05-28 13:17:26', '2016-05-14 20:08:11'),
(5, 'こちらは地獄の底の血の池で、ほかの罪人と一しょに、浮いたり沈んだりしていた陀多でございます。何しろどちらを見ても、まっ暗で、たまにそのくら暗からぼんやり浮き上っているものがあると思いますと、それは恐しい針の山の針が光るのでございますから、その心細さと云ったらございません。その上あたりは墓の中のようにしんと静まり返って、たまに聞えるものと云っては、ただ罪人がつく微な嘆息ばかりでございます。これはここへ落ちて来るほどの人間は、もうさまざまな地獄の責苦に疲れはてて、泣声を出す力さえなくなっているのでございましょう。ですからさすが大泥坊の陀多も、やはり血の池の血に咽びながら、まるで死にかかった蛙のように、ただもがいてばかり居りました。', '蜘蛛の糸-5', '芥川龍之介-5', '2016-05-28 13:16:09', '2016-05-09 11:52:51'),
(6, 'ところがある時の事でございます。何気なく陀多が頭を挙げて、血の池の空を眺めますと、そのひっそりとした暗の中を、遠い遠い天上から、銀色の蜘蛛の糸が、まるで人目にかかるのを恐れるように、一すじ細く光りながら、するすると自分の上へ垂れて参るのではございませんか。陀多はこれを見ると、思わず手を拍って喜びました。この糸に縋りついて、どこまでものぼって行けば、きっと地獄からぬけ出せるのに相違ございません。いや、うまく行くと、極楽へはいる事さえも出来ましょう。そうすれば、もう針の山へ追い上げられる事もなくなれば、血の池に沈められる事もある筈はございません。', '蜘蛛の糸-6', '芥川龍之介-6', '2016-05-28 13:19:27', '2016-05-14 20:08:07'),
(7, 'こう思いましたから陀多は、早速その蜘蛛の糸を両手でしっかりとつかみながら、一生懸命に上へ上へとたぐりのぼり始めました。元より大泥坊の事でございますから、こう云う事には昔から、慣れ切っているのでございます。', '蜘蛛の糸-7', '芥川龍之介-7', '2016-05-28 13:20:24', '2016-05-28 13:20:24');

--
-- ダンプしたテーブルのインデックス
--

--
-- テーブルのインデックス `board`
--
ALTER TABLE `board`
  ADD PRIMARY KEY (`row_no`),
  ADD UNIQUE KEY `row_no` (`row_no`);

--
-- ダンプしたテーブルのAUTO_INCREMENT
--

--
-- テーブルのAUTO_INCREMENT `board`
--
ALTER TABLE `board`
  MODIFY `row_no` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;


inner join で増殖して追加

inner join で条件を書かなければ、n 行あれば、n x n 行の結果を返します。その際、同じ表を a と b で別名定義して自己結合させます。

結果の行は、board の 定義に合わせて a 表のみから取得して、row_no は 自動採番なので null as row_no として先頭に作成します。

その結果をさらに board に insert する事によって、row_no は、新しく自動採番された行として挿入されます。その結果 a( 最初の行数 ) + n( 元の行数 ) * n( 元の行数 ) の行を登録する事になります。
insert into board
select
	null as row_no,a.body,a.subject,a.from,a.pdate,a.cdate
	from board a
inner join `board` b
※ もう一回すると 3192 件になるので、これ以上は注意して実行する必要があります。

乱数関数で日付データのみ、ばらつかせる

ここではさほど厳密にバラつかせる必要は無かったので、時間部分に適用しています。
※ PIPES_AS_CONCAT は、文字列結合に Oracle と同じ || を使用可能にする設定です。
SET sql_mode='PIPES_AS_CONCAT';

update board set pdate = cast('2016/05/28 0' || truncate(Rand()*10,0) || ':00' as datetime)



posted by lightbox at 2020-05-11 19:36 | MySQL | このブログの読者になる | 更新情報をチェックする

2020年05月06日


PDO MySQL のバインドを使用した標準的な記述( ロリポップ )

PHP の ドキュメント上の サンプルを踏襲しています

接続

接続時は必ず  PDOException をスローします。なので、setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) は実行されていません
<?php
session_cache_limiter('nocache');
session_start();

header( "Content-Type: text/html; charset=utf-8" );

/* ドライバ呼び出しを使用して MySQL データベースに接続する */
$dsn = 'mysql:host=mysql145.phy.lolipop.lan;dbname=LAA999999-mydb';
$user = 'LAA999999';
$password = 'password';

try {

	$dbh = new PDO($dsn, $user, $password);
	print "DB 接続に成功しました";

}
catch (PDOException $e) {

	echo '接続に失敗しました: ' . $e->getMessage();

}


// ***************************
// 解放( 接続解除 )
// ***************************
$dbh = null;


// ***************************
// デバッグ用
// ***************************
print "<pre>";
print_r($_GET);
print_r($_POST);
print_r($_SESSION);
print "</pre>";

?>


複数行の順次読込み

結果を簡単に確認する為に、text/plain で出力しています
<?php
session_cache_limiter('nocache');
session_start();

header( "Content-Type: text/plain; charset=utf-8" );

/* ドライバ呼び出しを使用して MySQL データベースに接続する */
$dsn = 'mysql:host=mysql145.phy.lolipop.lan;dbname=LAA999999-mydb';
$user = 'LAA999999';
$password = 'password';

try {

	// ***************************
	// 接続
	// ***************************
	$dbh = new PDO($dsn, $user, $password);
	// 接続以降で try 〜 catch を有効にする設定
	$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	print "DB 接続に成功しました\n";

}
catch (PDOException $e) {

	print '接続に失敗しました: ' . $e->getMessage();

}

// ***************************
// ループ読み出し
// ***************************
$sql = 'SELECT * from 社員マスタ where 氏名 like ?';
try {

	// まず準備する( prepare )
	$stmt = $dbh->prepare($sql);
	// SQL の変わる部分をバインドする
	// bindValue は、定数・変数どちらでも可
	$stmt->bindValue(1, "%田%", PDO::PARAM_STR);
	// 実行する
	$stmt->execute();

	// 読み出す( FETCH_BOTH : 両方 / FETCH_ORI_NEXT : 通常順次カーソル )
	while ($row = $stmt->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT)) {
		$data = "{$row[0]}\t{$row[1]}\t{$row[2]}\n";
		print $data;
		print_r( $row );
	}

	// ***************************
	// ステートメントの解放
	// ***************************
	$stmt = null;
}
catch (Exception $e) {
	print "読み出しに失敗しました: {$e->getMessage()}";
}

// ***************************
// 解放( 接続解除 )
// ***************************
$dbh = null;


// ***************************
// デバッグ用
// ***************************
print_r($_GET);
print_r($_POST);
print_r($_SESSION);

?>


読込みながら更新

<?php
session_cache_limiter('nocache');
session_start();

header( "Content-Type: text/plain; charset=utf-8" );

/* ドライバ呼び出しを使用して MySQL データベースに接続する */
$dsn = 'mysql:host=mysql145.phy.lolipop.lan;dbname=LAA999999-mydb';
$user = 'LAA999999';
$password = 'password';

try {

	// ***************************
	// 接続
	// ***************************
	$dbh = new PDO($dsn, $user, $password);
	// 接続以降で try 〜 catch を有効にする設定
	$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	print "DB 接続に成功しました\n";

}
catch (PDOException $e) {

	print '接続に失敗しました: ' . $e->getMessage();

}

// ***************************
// ループ読み出し
// ***************************
$sql = 'SELECT * from 社員マスタ where 氏名 like ?';
$sql2 = 'update 社員マスタ set 生年月日 = 生年月日 + 1 where 社員コード = ?';
try {

	// まず準備する( prepare )
	$stmt = $dbh->prepare($sql);
	// SQL の変わる部分をバインドする
	// bindValue は、定数・変数どちらでも可
	$stmt->bindValue(1, "%田%", PDO::PARAM_STR);
	// 実行する
	$stmt->execute();

 	// 更新用の SQL を準備する
	$stmt2 = $dbh->prepare($sql2);

	// 読み出す( FETCH_BOTH : 両方 / FETCH_ORI_NEXT : 通常順次カーソル )
	while ($row = $stmt->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT)) {
		$data = "{$row[0]}\t{$row[1]}\t{$row[2]}\n";
		print $data;
		print_r( $row );

		// 男性のみ更新
	 	if ( $row["性別"] == 0 ) {
			$stmt2->bindValue(1, $row["社員コード"], PDO::PARAM_STR);
			$stmt2->execute();
		}

	}

	// ***************************
	// ステートメントの解放
	// ***************************
	$stmt2 = null;
	$stmt = null;
}
catch (Exception $e) {
	print "読み出しに失敗しました: {$e->getMessage()}";
}

// ***************************
// 解放( 接続解除 )
// ***************************
$dbh = null;


// ***************************
// デバッグ用
// ***************************
print_r($_GET);
print_r($_POST);
print_r($_SESSION);

?>


このページの PDF


posted by lightbox at 2020-05-06 19:54 | PHP + データベース | このブログの読者になる | 更新情報をチェックする

2020年05月05日


jQuery + bootstrap.js で ajax の GET と POST を使用した DB テーブルを更新する UI テンプレート

実際のアプリケーションの UI 部分のみ取り出して、ブラウザでテストできるように構成しました。特に jQuery の ajax を用いたテンプレートとして流用できると思います。

初回の キー入力部分では、$.get で GET 読み込みを行っています。第二パスである更新時は $.ajax で POST を使用して送信しています。( POST では FormData オブジェクトを使用しています )

更新確認には、bootstrap のダイアログを使用して、一つのフォームで二つのデータ送信がコードとして別々に読めるようになっています。

実際の FORM の中に入力フィールドを配置して、HTML のチェック機能を利用できるようにしています。ブラウザの送信は、preventDefault() でキャンセルして、ajax でデータを送信するスタイルとなっています。

※ submit_type == "pass1" は、第一パス(キーの送信)です
<!DOCTYPE html>
<html>
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<meta charset="utf-8">
<head>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.7/js/tether.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.0/css/bootstrap.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.0/js/bootstrap.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>

<style>
body {
	margin: 20px;
}
</style>

<script>
// ▼ このコードのみでのテスト用変数
var submit_type = "pass1";
//var submit_type = "pass2";

$(function(){

	if ( submit_type == "pass1" ) {
		$("[name^='fld_'],#ref_btn").prop('disabled', true);
	}
	if ( submit_type == "pass2" ) {
		$("input[name='key_code']").prop('readonly', true);
		$("[name^='fld_'],#ref_btn").prop('disabled', false);
	}

	// **************************************
	// 確認処理
	// **************************************
	$("#base").on( "submit", function(event){

		// 更新確認ダイアログの表示の為、本来の送信処理はキャンセル
		event.preventDefault();

		// 入力したコードよりデータを取得する
		if ( submit_type == "pass1" ) {

			console.log("key_code");
			console.log(key_code);

			// Ajax で GET する
			$.get({
				url: "app-get.php",
				cache: false,
				data: { "key_code" : $(this).find("input[name='key_code']" ).val() }
			})
			.done(function( data, textStatus ){
				console.log( "status:" + textStatus );
				console.log( "data:" + JSON.stringify(data, null, "    ") );

				if ( data.status == 0 ) {

					// *************************************
					// コード部分を入力不可に設定
					// *************************************
					$("input[name='key_code']").prop('readonly', true);

					// *************************************
					// 明細部分を入力可能に変更
					// *************************************
					$("[name^='fld_'],#ref_btn").prop('disabled', false);

					// 氏名
					$("input[name='fld_name']").val( data.row["氏名"] );
					// フリガナ
					$("input[name='fld_kana']").val( data.row["フリガナ"] );
					// 給与
					$("input[name='fld_kyuyo']").val( data.row["給与"] );

					// 所属
					$("input[name='fld_syozoku']").val( data.row["所属"] );
					$("#ref_syozoku").text( data.row["所属名"] );

					// 性別
					$("select[name='fld_seibetu']").val( data.row["性別"] );
					// 生年月日
					$("input[name='fld_birth']").val( data.row["生年月日"].substring(0,10) );

					// フォーカスを設定
					$("input[name='fld_name']").focus();

					// コードをローカルストレージに保存
					localStorage["code"] = parent.$("input[name='key_code']").val();


					// エラーが無ければ次の処理を行えるようにする
					submit_type = "pass2";

				}

				// 対象データが無い場合
				if ( data.status == 1 ) {
					// エラーメッセージを表示
					toastr.error("入力された社員コードは存在しません");

					// エラー部分にフォーカスをセット
					$("input[name='key_code']").focus();
					// エラーが発生したフィールド内の文字列を選択する
					$("input[name='key_code']").select();

				}

				if ( data.status == -1 ) {
					// エラーメッセージを表示
					toastr.error("システムエラーです : SQL にあやまりがあります");

				}
				
			})
			// 失敗
			.fail(function(jqXHR, textStatus, errorThrown ){
				console.log( "status:" + textStatus );
				console.log( "errorThrown:" + errorThrown );

				// エラーメッセージを表示
				toastr.error("システムエラーです");

			})
			// 常に実行
			.always(function() {
			})
			;

		}


		// Bootstrap の モーダルダイアログの表示
		if ( submit_type == "pass2" ) {
			$("#update_check").modal();
		}

	});

	// **************************************
	// Bootstrap OK ボタン
	// ※ ここで第二パスの送信処理を確定
	// **************************************
	$("#data_update").on("click", function(){

		// Ajax で POSTする

		// 新規送信用オブジェクト
		var formData = new FormData();

		// ファイルオブジェクト
		formData.append("key_code", $("input[name='key_code']").val() );
		formData.append("fld_name", $("input[name='fld_name']").val() );
		formData.append("fld_kana", $("input[name='fld_kana']").val() );
		formData.append("fld_seibetu", $("select[name='fld_seibetu']").val() );
		formData.append("fld_birth", $("input[name='fld_birth']").val() );
		formData.append("fld_kyuyo", $("input[name='fld_kyuyo']").val() );
		formData.append("fld_syozoku", $("input[name='fld_syozoku']").val() );

		// **************************************
		// サーバ呼び出し
		// **************************************
		$.ajax({
			url: "app-update.php",
			type: "POST",
			data: formData,
			processData: false,  // jQuery がデータを処理しないよう指定
			contentType: false   // jQuery が contentType を設定しないよう指定
		})
		.done(function( data, textStatus ){
			console.log( "status:" + textStatus );
			console.log( "data:" + JSON.stringify(data, null, "    ") );

			// *************************************
			// コードを入力可に設定
			// *************************************
			$("input[name='key_code']").prop('readonly', false);

			// *************************************
			// 明細部分を入力不可に変更
			// *************************************
			$("[name^='fld_'],#ref_btn")
				.prop('disabled', true);

			// 氏名のクリア
			$("input[name='fld_name']").val( "" );
			// フリガナのクリア
			$("input[name='fld_kana']").val( "" );
			// 給与のクリア
			$("input[name='fld_kyuyo']").val( "" );

			// 所属のクリア
			$("input[name='fld_syozoku']").val( "" );
			$("#ref_syozoku").text("");

			// 性別の初期化
			$("select[name='fld_seibetu']").val( "0" );
			// 生年月日の初期化
			$("input[name='fld_birth']").val( "" );

			// フォーカスを設定
			$("input[name='key_code']").focus();
			
			// エラーが無ければ次の処理を行えるようにする
			submit_type = "pass1";

			toastr.info("更新されました");


		})
		.fail(function(jqXHR, textStatus, errorThrown ){
			console.log( "code:" + jqXHR.status );
			console.log( "status:" + textStatus );
			console.log( "errorThrown:" + errorThrown );
		})
		.always(function() {
		})
		;



	});

});
</script>
</head>
<body>
<div style='float:right'>
	<input
		id="action_reset"
		type="button"
		value="リセット"
		class="btn btn-danger mr-3"
		onclick="location.href='syain-upd.html'">

	<input
		id="action_copy"
		type="submit"
		value="送信"
		class="btn btn-primary"
		onclick="$('#action').click();">
</div>

<form id="base" method="post" target="_self" style='clear:both'>
	<div>
		<div class="left">社員コード</div>
		<div class="right">
			<input
				type="text"
				id="key_code"
				name="key_code"
				class="unit"
				value="" required >
		</div>
	</div>
	<div>
		<div class="left">氏名</div>
		<div class="right">
			<input
				type="text"
				id="fld_name"
				name="fld_name"
				class="unit"
				value="" required >
		</div>
	</div>
	<div>
		<div class="left">フリガナ</div>
		<div class="right">
			<input
				type="text"
				id="fld_kana"
				name="fld_kana"
				class="unit"
				value=""  >
		</div>
	</div>
	<div>
		<div class="left">給与</div>
		<div class="right">
			<input
				type="text"
				id="fld_kyuyo"
				name="fld_kyuyo"
				class="unit"
				value="" required maxlength='7' pattern='\d+' >
		</div>
	</div>
	<div>
		<div class="left">所属</div>
		<div class="right">
			<div class="input-group">
				<input
					type="text"
					id="fld_syozoku"
					name="fld_syozoku"
					class="unit"
					value=""
					maxlength="4">
		
			</div>
		</div>
	</div>
 
	<div>
		<div class="left">性別</div>
		<div class="right">
			<select class="unit" name="fld_seibetu" id="fld_seibetu" >
				<option value="0">男性</option>
				<option value="1">女性</option>
			</select>
		</div>
	</div>

	<div>
		<div class="left">生年月日</div>
		<div class="right">
			<div class="input-group">
				<input type="text" id="fld_birth" name="fld_birth">
				<button
					type="button"
					class="btn"
					onclick='$(this).prev().val("");'>×</button>
			</div>
		</div>
	</div>

	<div>
		<input
		id="action"
			type="submit"
			value="送信"
			class="btn btn-primary unit mt-5"
			title="mt5 は margin-top の略で 1〜5">
	</div>

</form>

<div class="modal fade" id="update_check" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
	<div class="modal-dialog" role="document">
		<div class="modal-content">

			<div class="modal-header">
				<h5 class="modal-title">確認</h5>
				<button type="button" class="close" data-dismiss="modal" aria-label="Close">
					<span aria-hidden="true">&times;</span>
				</button>
			</div>
			
			<div class="modal-body">
			更新しますか?
			</div>

			<div class="modal-footer">
				<button id="data_update" type="button" class="btn btn-default" data-dismiss="modal">OK</button>
			</div>

		</div>
	</div>
</div>
</body>
</html>


このページのPDF




posted by lightbox at 2020-05-05 10:03 | jQuery | このブログの読者になる | 更新情報をチェックする

2020年05月02日


C#( Form ) : ウインドウ枠の無い吹き出しの作成

昔 Flex で透明ウィンドウ作った事があったので、C# でもできるだろうと調べてみたら普通にありました。凝っても仕方無いので向きの切り替えとかコンテキストメニュー等は好みで追加すればいいと思います。

オンラインで授業やるのに欲しいなぁと思い作ってみましたので、自分はこれで十分です。

エディタ部分は、richTextEditor です。( 縦スクロールバーが文字列があふれた時に表示されます )
using System;
using System.Drawing;
using System.Windows.Forms;

namespace TransForm
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			// フォームの境界線とタイトルを表示しない
			this.FormBorderStyle = FormBorderStyle.None;
			// 画像サイズ
			this.Size = new Size(584, 396);
			// 画像を読み込む( 吹き出し部分以外青 )
			Bitmap bmp = new Bitmap("fu2.png");
			// 透明にする色
			Color tColor = Color.Blue;
			// 背景画像に指定する
			this.BackgroundImage = bmp;

			// 透明を指定する
			this.TransparencyKey = tColor;

			// ウインドウを richTextBox 以外で移動できるようにする
			this.MouseDown +=
				new MouseEventHandler(Form1_MouseDown);
			this.MouseMove +=
				new MouseEventHandler(Form1_MouseMove);
		}

		// マウスのクリック位置
		private Point mousePoint;

		// マウスのボタンが押された
		private void Form1_MouseDown(object sender, MouseEventArgs e)
		{
			if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
			{
				// 押された位置
				mousePoint = new Point(e.X, e.Y);
			}
		}

		// マウスのドラッグ処理
		private void Form1_MouseMove(object sender,	MouseEventArgs e)
		{
			if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
			{
				this.Left += e.X - mousePoint.X;
				this.Top += e.Y - mousePoint.Y;
			}
		}
	}
}




posted by lightbox at 2020-05-02 18:11 | VS(C#) | このブログの読者になる | 更新情報をチェックする
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 終わり