[C#]DataGridViewの変更をDataTableに反映させる

DataGridViewに次のようにチェックボックスを作ってあるとします。

            DataColumn _dc1 = new DataColumn("check", typeof(bool));
            DataColumn _dc2 = new DataColumn("name", typeof(string));
            DataColumn _dc3 = new DataColumn("age", typeof(uint));
            DataTable _dt = new DataTable();
            _dt.Columns.Add(_dc1);
            _dt.Columns.Add(_dc2);
            _dt.Columns.Add(_dc3);
            DataGridView dgv = new DataGridView();

            DataRow _dr = _dt.NewRow();
            _dr["name"] = "本田";
            _dr["age"] = 31;
            _dt.Rows.Add(_dr);

            _dr["name"] = "香川";
            _dr["age"] = 28;
            _dt.Rows.Add(_dr);

            _dr["name"] = "長友";
            _dr["age"] = 30;
            _dt.Rows.Add(_dr);
            
            _dr["name"] = "吉田";
            _dr["age"] = 28;
            _dt.Rows.Add(_dr);

            dgv.DataSource = _dt;

で、DataGridViewに表示されたチェックボックスをつけたあとに、次のように取得しようとしても、最後にチェックしたひとつが取得できていません。

            DataRow[] _selected_rows 
                = ((DataTable)dgv.DataSource).Select("check=true");

そこで、登場するのがEndEdit()。

DataGridViewを操作し始めると、自動的にBigenEdit()メソッドが呼び出されているらしく、それを終わらせるためにEndEdit()を呼び出さないといけないそうです。

というわけで、DataGridViewと、バインドされているDataSourceのDataRowViewでEndEdit()メソッドを実行すればいいと。

            dgv.EndEdit();
            ((DataRowView)dgv.CurrentRow.DataBoundItem).EndEdit();


            DataRow[] _selected_rows 
                = ((DataTable)dataGridView_dataList.DataSource).Select("check=true");

MySQL 重複するデータの取得

MySQLで重複した値をもつ行を取得する方法

まずは、データを作るところから。

CREATE TABLE test ( id BIGINT NOT NULL , name TEXT NOT NULL , age SMALLINT NOT NULL ) ENGINE = InnoDB;
INSERT INTO test (id, name, age) VALUES ('1', 'nagatomo', '31');
INSERT INTO test (id, name, age) VALUES ('2', 'yoshida', '28');
INSERT INTO test (id, name, age) VALUES ('3', 'honda', '30');
INSERT INTO test (id, name, age) VALUES ('4', 'okazaki', '31');
INSERT INTO test (id, name, age) VALUES ('5', 'kagaawa', '28');
INSERT INTO test (id, name, age) VALUES ('6', 'usami', '25');
INSERT INTO test (id, name, age) VALUES ('3', 'kubo', '23');

そして、idが重複しているデータをピックアップします。

mysql> SELECT * FROM test GROUP BY id HAVING COUNT(*) >= 2;

 HAVING COUNT(*) >= 2 で、2つ以上重複している行だけをピックアップします。

 

MySQL 条件つきでCOUNT、SUM、AVGする

SELECT分で、WHEREで条件を指定して取り出したデータを、COUNTしたり、SUM(合計)したり、AVG(平均)したりする方法。

まずは、サンプルデータを作ります。

CREATE TABLE test ( id BIGINT , name TEXT , age SMALLINT ) ;
INSERT INTO test (id, name, age) VALUES ('1', 'nagatomo', '31');
INSERT INTO test (id, name, age) VALUES ('2', 'yoshida', '28');
INSERT INTO test (id, name, age) VALUES ('3', 'honda', '30');
INSERT INTO test (id, name, age) VALUES ('4', 'okazaki', '31');
INSERT INTO test (id, name, age) VALUES ('5', 'kagaawa', '28');
INSERT INTO test (id, name, age) VALUES ('6', 'usami', '25');

ここから、ageの数、合計、平均を取得します。

/*全数*/
SELECT COUNT(*) FROM test;

/*全合計*/
SELECT SUM(age) FROM test;

/*全平均*/
SELECT AVG(age) FROM test;

つぎに条件付きで取得する場合。以下の例では、30才以上の数、合計、平均を取得します。

/*30才以上の人数*/
SELECT COUNT(age>=30 OR NULL) FROM test;

/*30才以上の合計*/
SELECT SUM(CASE WHEN age>=30 THEN age ELSE 0 END) FROM test;

/*30才以上の平均*/
SELECT SUM(CASE WHEN age>=30 THEN age ELSE 0 END)/COUNT(age>=30 OR NULL) FROM test;

COUNTは単にCOUNT(age>=30)だと、ちゃんと数えてくれません。なんでも、COUNTは()内の結果が、TRUEでもFALSEでも1としてカウントしてしまうからだそうです。
つまり、TRUEかNULLかでカウントしなければならんということです。

TRUE → 1
FALSE → 1

ということで、 OR NULLをつけるとうまくいくというけれど、なんで?
というのを、検証してくださっている方がいて、結論から言うと、FALSEをNULLに変換しているわけですが、そのロジックはというと、

TRUE OR NULL → TRUE → 1
FALSE OR NULL → NULL → 0

となるからだそうです。

というわけで、 OR NULL とすることで、TRUEのときにはTRUE、FALSEのときにはNULLとなって、COUNT(age>=30 OR NULL) でちゃんとうまくいくと。

つぎにSUM()ですが、CASE WHEN文を使えばいいそうです。
ちなみに、SUM(age>=30 OR NULL) とやると、COUNTと同じ結果がかえってきます。TRUEなら1ってことで1×数なので、そりゃそうか。

つぎに平均ですが、AVG()にもCASE WHEN文は使えますが、平均する母数はそのままなので、「30才以上の平均」とはなりません。(サンプルデータだと、(31+30+31)÷6 となってしまいますので、SUMとCOUNTの組み合わせで平均を計算します。

ちなみに、OR NULL や、CASEを使わずに、IFを使ってもできます。こんな感じで。

/*30才以上の人数*/
SELECT COUNT(IF( age>=30 , age , null )) FROM test;

/*30才以上の合計*/
SELECT SUM(IF( age>=30 , age , 0 )) FROM test;

/*30才以上の平均*/
SELECT SUM(IF( age>=30 , age , 0 )) / COUNT(age>=30 OR NULL) FROM test;

/*30才以上の平均*/
SELECT SUM(IF( age>=30 , age ,0 )) / COUNT(IF( age>=30 , age , null )) FROM test;	

以上、取得したデータから条件で数、合計、平均を取り出せますが、実際、この程度のデータと条件であれば、WHERE句で age>=30 とすればいいのですが、たとえば、30以上と、30未満の合計などを一度に取得したいときは、スマートに記述できていいです。こんな感じで。

/*30才以上の人数*/
SELECT COUNT(age>=30 OR NULL) as above30 , COUNT(age<30 OR NULL) as under30 FROM test;

/*30才以上の合計*/
SELECT SUM(CASE WHEN age>=30 THEN age ELSE 0 END) as above30 ,
	SUM(CASE WHEN age<30 THEN age ELSE 0 END) as under30
	FROM test;

/*30才以上の平均*/
SELECT SUM(CASE WHEN age>=30 THEN age ELSE 0 END) / COUNT(age>=30 OR NULL) as above30 ,
	SUM(CASE WHEN age<30 THEN age ELSE 0 END) / COUNT(age<30 OR NULL) as under30
	FROM test;

参考になったサイトさん:
COUNT:https://www.softel.co.jp/blogs/tech/archives/3267
SUM:http://d.hatena.ne.jp/deeeki/20090521/sumcasewhen
AVG:https://blogs.yahoo.co.jp/warp_green_3/23908557.html

C# ダイアログフォームのOKボタンをクリックしてもフォームを閉じない

ダイアログを作って、AcceptButtonプロパティに設定したOKボタンをクリックすると、そのダイアログフォームは閉じてしまいますが、条件が整っていないときは、OKボタンを押しても閉じないようにするには次のようにします。

checkbox1にチェックがついていなければ、OKボタンを押しても閉じることはできません。

        private void button_OK_Click(object sender, EventArgs e)
        {
            if (checkbox1.Checkd == false)
            {
                close_permition = false;
            }
        }

        bool close_permition = true;

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!close_permition)
            {
                close_permition = true;
                e.Cancel = true;
            }
        }

OKボタンを押したときだけ、checkbox1を確認してその結果をclose_permitionに保存します。

FormClosingイベントで、close_permitionがfalseなら、
e.Cancel = true として、フォームを閉じることをキャンセルします。

単に、

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (checkbox1.Checkd == false)
            {
                e.Cancel = true;
            }
        }

としてしまうと、キャンセルボタンや、閉じるボタンをクリックしたときに、checkbox1の影響を受けてしまうので、前述のようにしないといけないよ。というお話でした。

Master Slider でページボタンをオンマウスで表示する

スライドショーのプラグインとして、とても使い勝手のいい、Master Sliderを使っているのですが、左右にスライドさせるためのボタンが大きくて、肝心のバナーを隠してしまっているので、マウスポインターが上に来た時だけ、常時させるようにする方法。

CSSや、JQueryで、hoverを使うと、うまく表示非表示を切り替えられなかったので、マウスポインタの座標と、スライダーの座標をチェックして、範囲内にあれば、ボタンを表示、範囲外なら非表示となるようにしています。

jQuery(function($) {
    $(document).ready(function () {
        var show = 0;
        $(window).mousemove(
            function(e){
                var offset = $(".ms-container").offset();
                var mswidth = $(".ms-container").width();
                var msheight = $(".ms-container").height();
                console.log('top: ' + offset.left + mswidth );
                console.log('top: ' +  e.pageX );
                if(offset.left < e.pageX
                        && (offset.left + mswidth) > e.pageX
                        && offset.top < e.pageY
                        && (offset.top + msheight) > e.pageY
                ){
                    $(".ms-nav-next ,  .ms-nav-prev ").show();
                }else{
                    $(".ms-nav-next ,  .ms-nav-prev ").hide();

                }
            }
        );
    });
});

inkscapeでDXFデータを出力する

「NC工作機械で加工したいので、絵をDXFデータにできない?」という相談がありまして、とりあえず、Inkscape(ver.0.91)でトライすることに。

まずは、下絵をInkscapeに貼り付けて、その上をトレース。

そして、「名前をつけて保存」で保存形式をDXFにして保存しようとすると、なぜかエラーに。

そこで、調べてみたところ、次のようにすればいいことがわかりました。

  1. 「名前をつけて保存」のときに、プレーンSVGで一旦保存する。
  2. 保存したプレーンSVGをInkscapeで読み込む
  3. 「名前をつけて保存」で保存形式をDXFにして保存

他にも試してだめだったこと

他にも、Inkscape(ver.0.91)を0.92にバージョンアップすればいいのか、と試してみましたが、だめでした。

また、プレーンSVGをフリーツールで変換しようとしましたが、これもだめでした。
試したのは、

convertio
https://convertio.co/ja/svg-dxf/

VectorToVector
http://www.vector.co.jp/soft/win95/business/se438196.html

いずれで変換しても、ちゃんと変換できませんでした。

 

WordPressのエディタでBボタンをStrongではなくBタグにするプラグイン

WordPressの投稿や固定ページの本文を編集する、ビジュアルエディタとテキストエディタで、Bボタンをクリックすると、Strongタグになります。同様に、Iボタンをクリックすると、emタグになりますが、これらは、装飾的に使うべきではないタグなので、bタグとiタグにしたいときがあります。

そんなときのために、さくっとインストールするだけの、便利なプラグインを作りました。

BI Button Changer

今回、作ったプラグインを、WordPressの公式ディレクトリに、はじめて登録しました。
プラグインの内容としては、

【解決】WordPressのビジュアルエディタでBとIがstrongとemタグになってしまう

の内容と全く同じです。

使い方は、ただプラグインをインストールするだけ。
それだけで、ビジュアルエディタとテキストエディタで、Bボタンをクリックするとbタグ、Iボタンをクリックするとiタグになります。

WordPressプラグインディレクトリへの登録

プラグインの作り方は、こちらを参考にするとわかりやすいです。
http://oxynotes.com/?p=9321
http://www.webopixel.net/wordpress/631.html

プラグインディレクトリへの登録方法は、こちらを参考にさせていただきました。
http://oxynotes.com/?p=9436
https://yyengine.jp/blog/yyengine/wp-plugin-add/

ありがとうございましたー

 

 

 

WordPressでメディアのURLを取得する

WordPressでは、アップロードした画像や動画などは、メディアとして管理されます。

投稿や固定ページに貼り付けた画像などは、「添付した画像」などといいます。

「メディア」で管理することができますが、基本的には投稿や固定ページに添付されていることが前提なことがおおいですが、そうではなくて、メディアの中から特定の画像を一覧で表示したいときがありあす。

そんなときは、WP_Queryで取り出して表示するのがいいです。

画像の一覧を取得する

$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$terms = get_terms( 'tenant-category', '' );
$the_query = new WP_Query( 
	array(
		'post_status' => 'any',
		'post_type' => 'attachment' ,
		'post_mime_type' => 'image' ,
		'posts_per_page' => 12 ,
		'nopaging' => false, 
		'paged' => $paged,
		'tax_query' => array(
			array(
				'taxonomy' => 'media_category',
				'field'	   => 'slug',
				'terms'	   => 'contest',
			)
			)	
		)
	);

if ($the_query->have_posts()) : while ($the_query->have_posts()) : $the_query->the_post(); 
		
	the_attachment_link( $the_query->post->ID ); //メディアをリンク付きで出力する

	echo wp_get_attachment_link( $the_query->post->ID , 'thumbnail' ); //メディアへのリンクをHTML付きで返す

	echo wp_get_attachment_url( $the_query->post->ID ); //メディアのURLを返す
	
	$images = wp_get_attachment_image_src( $the_query->post->ID, 'medium' ); //添付された画像のURLとサイズを配列で返す
	echo '<img src="' . $images[0] . '" width="' . $images[1] . '" height="' . $images[2] . '"/>';

endwhile;
else: 
endif;
wp_reset_query();

WP_Queryのpost_typeにattachmentを指定して取り出します。

the_attachment_link を使うと、HTMLタグごと出力してくれるので、ただ貼り付けるだけで画像を出力してくれます。が。出力サイズをフルサイズかサムネイルしか選べないので、
wp_get_attachment_link をったほうが便利です。

ただ、もうちょっと細かいことがしたかったら、URLを直接取得してタグは自力でかいたほうがいいこともあります。そんなときは、wp_get_attachment_url を使います。
あるいは、wp_get_attachment_image_src を使うと、画像のURLとサイズを配列で取得できます。

カテゴリに指定されたものだけ取得する

メディアにカテゴリをつけていた場合、そのカテゴリで出力する画像を指定できます。

WP_Queryのargsを次のようにtax_queryを追加します。

$the_query = new WP_Query( 
	array(
		'post_status' => 'any',
		'post_type' => 'attachment' ,
		'post_mime_type' => 'image' ,
		'posts_per_page' => 12 ,
		'nopaging' => false, 
		'paged' => $paged,
		'tax_query' => array(
			array(
				'taxonomy' => 'media_category',
				'field'	   => 'slug',
				'terms'	   => 'contest',
			)
			)	
		)
	);

固定ページや投稿ページに使われている画像を取得する

特定の固定ページや投稿ページに使われている(添付されている)画像を取得したいときは、get_attached_media を使います。以下の例では、get_the_ID を使っているので、ループの中で使います。

if ( have_posts() ) while ( have_posts() ) : the_post();

	$medias = get_attached_media( 'image', get_the_ID() );
	foreach($medias as $media){
		the_attachment_link( $media->ID );
	}

endwhile;

【解決】WordPressのビジュアルエディタでBとIがstrongとemタグになってしまう

【追記】プラグイン化しました。BI Button Changer

詳しくはこちら→WordPressのエディタでBボタンをStrongではなくBタグにするプラグイン

 

WordPressのビジュアルエディタは本当に便利でありがたい限りですが、大きなお世話なところも少なからずあるわけで。

その中で、もっともよろしくないと思うのが、Bボタンと、Iボタン。

Bはボールドで太文字になるので、当然bタグがあてがわれると思っていたら、strongタグになってしまいます。

Iも同様に、イタリックで斜体になるので、iタグがあてがわれると思ったら、emタグになってしまいます。

strongやemは、h1,h2などの見出しタグ同様、検索エンジンは重要なワードとして認識する。ゆえに適材適所で使う分にはいいが、乱発すると「意図的に検索エンジンをだまそうとしている」のような受け止められ方をされて、ペナルティを受ける場合がある。よって、strongタグやemタグを乱用するのはSEO上よろしくない。
みたいに言われています。

にもかかわらず、ワンクリックでstrongとemが使えてしまうので、これを知らずにガンガン使うとまずいので、BボタンやIボタンは、実質ほとんど使いません。

そんなことをわかっている人はいいのですが、SEOという言葉すら知らないクライアントさんにお渡しする際には、これは非常にまずいわけです。

なので、これまではAddQuicktag を使ったり、Visual Editor Custom Buttons をつかって、「BボタンとかIボタンは使わずに、こっちを使ってください。なぜなら、SEOという考え方があって、うんたらかんら・・・」という説明をしていたわけですが、いい加減どうにかならないか、と一念発起して、調べてたらこんな方法が。

http://wordpress.stackexchange.com/questions/168182/should-the-wp-post-editor-b-bold-button-be-inserting-a-b-tag-instead-of-str

早速やってみました。

ビジュアルエディタのBボタンとIボタンの出力を変更

function.phpあたりに、以下をいれます。

function modify_formats($settings){
   $formats = array(
     'bold' => array('inline' => 'b'),
     'italic' => array('inline' => 'i')
    );
    $settings['formats'] = json_encode( $formats );
    return $settings;
}
add_filter('tiny_mce_before_init', 'modify_formats');

するとどうでしょう!
Bボタンでbタグ、Iボタンでiタグにばっちりなってますね!

テキストエディタのBボタンとIボタンを変更

ただ、テキストエディタでは、相変わらずstrongとemなので、こっちも変えたい。

そこで、functioni.php 以下を追加します。
テキストエディタでは、置き換える方法がわからなかったので、一旦既存のBとIボタンは取り除きます。quicktags_settings フックで、strongとemがない状態にします。

//テキストエディタから、strongとemボタンを除く
function default_quicktags($qtInit) {
  //$qtInit['buttons'] = 'link,em,strong,block,del,ins,img,ul,li,ol,code,more,spell,close,fullscreen';//こっちがデフォルト
  $qtInit['buttons'] = 'link,block,del,ins,img,ul,li,ol,code,more,spell,close,fullscreen';
  return $qtInit;
}
add_filter('quicktags_settings', 'default_quicktags', 10, 1);

それから、admin_print_footer_scripts フックで、JSを追加して、bとiボタンを追加します。

//テキストエディタにBとIボタンを追加
function appthemes_add_quicktags() {
    if (wp_script_is('quicktags')){
?>
    <script type="text/javascript">
        QTags.addButton( 'eg_bold', 'B', '<b>', '</b>', 'b', 'ボールド', 1 );
	QTags.addButton( 'eg_i', 'I', '<i>', '</i>', 'i', 'イタリック', 2 );
    </script>
<?php
    }
}
add_action( 'admin_print_footer_scripts', 'appthemes_add_quicktags' );

これで、大丈夫なはず。

すでに使ってしまったstrongタグとemタグをフロント出力時に置換

あと、すでに散々strongタグやemを使いまくってしまった、という場合には、表示するときにbとiタグに置換する方法もあります。同じくfunction.phpに以下をいれます。(ただし、strongタグやemタグを意図して使いたくても置換されていまいます。)

//strongタグをbタグに置換
function change_b_to_strong($content){
    $content = str_replace('<strong>', '<b>', $content);
    $content = str_replace('</strong>', '</b>', $content);
    return $content;
}
add_filter( 'the_content', 'change_b_to_strong' );

BボタンとIボタンをクリックしたときに、bタグ、iタグにする方法まとめ

function.phpに以下をまるっと入れれば、Bボタンを押してもstrongタグにならずにbタグに。Iボタンを押しても、emタグにならずにiタグになります。

//ビジュアルエディタのbボタンとiボタンをbタグとiタグに置き換える
function modify_formats($settings){
   $formats = array(
     'bold' => array('inline' => 'b'),
     'italic' => array('inline' => 'i')
    );
    $settings['formats'] = json_encode( $formats );
    return $settings;
}
add_filter('tiny_mce_before_init', 'modify_formats');

//テキストエディタから、strongとemボタンを除く
function default_quicktags($qtInit) {
  //$qtInit['buttons'] = 'link,em,strong,block,del,ins,img,ul,li,ol,code,more,spell,close,fullscreen';//こっちがデフォルト
  $qtInit['buttons'] = 'link,block,del,ins,img,ul,li,ol,code,more,spell,close,fullscreen';
  return $qtInit;
}
add_filter('quicktags_settings', 'default_quicktags', 10, 1);

//テキストエディタにBとIボタンを追加
function appthemes_add_quicktags() {
    if (wp_script_is('quicktags')){
?>
    <script type="text/javascript">
        QTags.addButton( 'eg_bold', 'B', '<b>', '</b>', 'B', 'ボールド', 1 );
	QTags.addButton( 'eg_i', 'I', '<i>', '</i>', 'B', 'イタリック', 2 );
    </script>
<?php
    }
}
add_action( 'admin_print_footer_scripts', 'appthemes_add_quicktags' );

参考サイト

クイックタグAPI

https://wpdocs.osdn.jp/%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%BF%E3%82%B0API

 

テキストエディタから、クイックタグボタンをつけたり外したりする方法

http://myownhomeserver.com/2011/10/wordpress-addremove-quicktags-simple-editor-buttons-in-3-3/

 

さくらインターネットでドメイン設定ができない

あるクライアントさんから、さくらインターネットさんを利用しているが、ドメインを取得しても登録できない、という相談があり対応しました。

さくらインターネットの会員ページから、独自ドメインの取得をすませ、レンタルサーバーのコントロールパネルからドメインの設定をしようとするのですが、「指定されたドメイン名は登録されています」となります。

指定されたドメイン名は登録されています

もちろん、他ではつかっていません。

で、さくらインターネットに問い合わせたところ、

現在の設定を調査いたしましたが、[toyonaka-souseijuku.org]のゾーン
情報が残っておりますため、以下を参考の上、ゾーン情報の削除作業を
お願いいたします。

▼ゾーン情報の削除
https://help.sakura.ad.jp/hc/ja/articles/206207381#ac040

ゾーン情報の削除後、必ず2時間経過いたしましてから、先に親ドメイン
[toyonaka-souseijuku.org]をサーバに設定いただき、サブドメインが
必要である場合は、その後サーバへ設定ください。

※ドメインは設定後、インターネット全体に行き渡るまで数時間から
 48時間程度かかる場合がございます。 

ということで、早速クライアントさんにお願いして、

https://help.sakura.ad.jp/hc/ja/articles/206207381#ac040

こちらを参考に、「ゾーン情報の削除」をしてもらいました。

その後、無事ドメインを設定できました。