■
http://www.cyokodog.net/blog/first-struts2/ ・セットアップ関係 http://qiita.com/alpha_pz/items/bd1fc9575a920f1560c8 旧時代の名残り Struts2は標準でテンプレートエンジンであるFreeMarkerを使って、HTML4時代のUI+JavaScriptの生成やタグの生成をします。 ただしこの自動生成するタグ、今となっては余計なお世話状態であり、HTMLのタグについては標準のHTMLだけを出して欲しいことが多々あります。 今回はそれをさせない方法です。 プロパティファイルに次の宣言をするだけ struts.propertiesファイルに、以下の1行を記載します。 struts.properties struts.ui.theme=simple ・起動時エラー関係 http://qiita.com/alpha_pz/items/e273faff1cc8b4a1dc7f Struts2.5←2.3.xの移行について http://stackoverflow.com/questions/28167771/java-lang-classnotfoundexception-org-apache-struts2-dispatcher-ng-filter-struts if you are using struts2 version 2.5 you need to change from org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter to org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter http://oshiete.goo.ne.jp/qa/7873045.html ◆フィルタを変更します。 サンプルにある org.apache.struts2.dispatcher.FilterDispatcherは現在、非推奨です。 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterをお使いください。 ◆Actionクラス @Results、@Resultアノテーションは、Struts2.1よりConventionプラグインへ移行しましたので、インポートするパッケージが異なります。 import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; ◇Result指定 @Resultで指定する属性も変更になりました。 @Result(name = "hello1", location = "index.jsp") このように、locationを使います。 また、type属性も、クラス名.classではなくなり、文字列(エイリアス)で指定します。 @Result(name = "hello2", location = "jump.jsp", type = "redirect"), @Result(name = "recipe", location = "jump!recipe", type = "redirectAction"), http://aoking.hatenablog.jp/entry/20121031/1351641785 くらすぷらっとふぉーむ ・struts 2.3 http://d.hatena.ne.jp/shishido-felica/20140529/1401330413 import org.apache.struts2.config.Result; がないってエラーが出る。 解決方法 struts2-codebehind-plugin-2.3.16.3.jar を追加。 ・struts 2.5 http://qiita.com/alpha_pz/items/4a97df916102dad2e2bc @Namespace("/sample") @ParentPackage("struts-default") @Results({ @Result(name = ActionSupport.SUCCESS, location = "index.jsp" , type="dispatcher"), }) @ExceptionMappings({ @ExceptionMapping(exception="java.lang.Exception" , result="exception") }) public class SampleAction extends ActionSupport { @Action("display") public String sample() throws Exception { return SUCCESS; } }
■
- https://www.sitepoint.com/call-javascript-function-string-without-using-eval/"How to Call a JavaScript Function From a String Without Using eval
- http://stackoverflow.com/questions/21088514/access-session-on-view-page-in-asp-net-mvc"razorからsessionの値を取得
- http://blog.codable.co.jp/entry/2015/02/21/010448"Razor レイアウト - Codable Tech Blog
- http://qiita.com/tonkotsuboy_com/items/d1b3cf45ae5135441f9b"AJAX通信をするときはタイムアウト処理を必ず入れてほしい(切実) - Qiita
- http://happyskiing.blog89.fc2.com/blog-entry-9.html"とあるSEの奮闘記 [ASP.NET MVC3] AJAXを使用した部分更新
- http://codezine.jp/article/detail/6378?p=2"ASP.NET MVC 3におけるDI実装のポイント (2/4):CodeZine(コードジン)
- http://www.atmarkit.co.jp/ait/articles/0904/10/news113_5.html"連載:ASP.NET MVC入門:第1回 ASP.NET MVCフレームワーク 基本のキ (5/5) - @IT
- http://papa-pad.seesaa.net/article/404590932.html"ASP.NET MVC5を始めるにあたり: 知食物メモ
- http://matome.naver.jp/odai/2140474256719291501?page=2"ASP.NET MVCを勉強するときはまずここ! - NAVER まとめ
- https://books.google.co.jp/books?id=SAlTBgAAQBAJ&printsec=frontcover&dq=asp.net+mvc+5+%E5%AE%9F%E8%B7%B5%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&hl=ja&sa=X&redir_esc=y#v=onepage&q=asp.net%20mvc%205%20%E5%AE%9F%E8%B7%B5%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&f=false"ASP.NET MVC5実践プログラミング - 山田祥寛 - Google ブックス
- http://aspmvc.tokumori-domain.com/intro/base3/"開発メモ
- https://codezine.jp/article/detail/1048?p=2"ASP.NETのセッションをタイプセーフに取り扱うクラスの作成 (2/2):CodeZine(コードジン)
- http://miso-soup3.hateblo.jp/entry/2013/12/09/073251"ASP.NET MVC セッション状態の値を操作してみる - miso_soup3 Blog
- http://kazunori-kimura.github.io/introduction-to-asp-dot-net/step2.1/step2.1.html"introduction to asp dot net - ASP.NET勉強会
- http://codezine.jp/article/detail/4354?p=4"ASP.NET MVCの開発応用編1 ~リポジトリパターンをマスターする~ (4/5):CodeZine(コードジン)
◆
・Java JSP化 画面の項目の配置が期待通りにならない時 画面の一部レイアウトがずれている場合の対処法 例)ボタン モックと開発中画面をIEの開発者ツールで確認し、 該当部分を右クリック⇒HTML要素として編集 で該当部分をそれぞれ見比べて確認 Eclipse 使い方 ショートカットキー 縦コピー(矩形選択) SHIFT+ALT+A 一杯表示しすぎて隠れているソースコードを表示 CTRL+E または、CTRL+SHIFT+E ファイル検索 CTRL+H 型名検索 CTRL+SHIFT+R ブレークポイント設定 CTRL+SHIFT+B ブックマークを設定するショートカットキーがない場合 ⇒行番号のあたりで右クリック⇒ブックマークの追加(切り替え) インデント整形(HTML,JSPに使うと全角スペースが消えてしまうため、使用する前に要確認) CTRL+SHIFT+F ⇒CTRL+ALT+↓でタグの範囲を指定してレイアウトを調整する方がたぶん間違いない 選択した単語をファイル内で検索 単語を選択した状態でCtrl+K Eclipse 事前設定 ウィンドゥ⇒設定⇒色とフォント⇒テキストフォント メイリオ 10以上 Eclipse Winmergeは相性が悪いから使わない方がいいい Eclipse ビルド時のエラー確認 ウィンドウ⇒ビューの表示⇒その他⇒問題 Eclipse 起動時にワークスペースをクリーン(起動時の引数追加) "C:\eclipse\eclipse.exe -clean.cmd" リソ-スを開く(Ctrl+SHIFT+R)でclassファイルが表示されないようにする リソースを開くで開いた画面の右上の▼をクリック、派生リソースのチェックOFF jquery注意点 idにぴりおどやコロン(:)を用いる時は、バックスラッシュ(\\)でエスケープする必要あり JSP コントロールの制御 jsp上は、hidden="true"などと値を直接格納せず、 hidden="${hogehogeForm.hiddenFlg == 'true'}"のように、Beanから取得した値で判断させる コンソールログを確認する方法 IEで開き、開発者ツールのコンソールで確認 Eclipseのコンソールには出ないので注意 CSS設計 term-area-padding ⇒やめたい、意味がない これをすると文字を赤くするにもクラスが必要 このテーブルの設定、みたいな名前にする パーセント指定、px指定はすべて排除(emとか使う) Javascript ボタンクリックでボタンの色を変更1 hoge = function() { var cnt = 0; $(':checked').each(function() { if($(this).val() === hogeConst.YES) { cnt += 1; } }); return cnt; }; fuga = fuction(e) { if(hoge() > 0) { $('btn-submit').removeClass('disabled'); } else { $('btn-submit').addClass('disabled'); } }; $(document).ready(function() { // DOM読み込み後処理 JQuery("input:checkbox").click(fuga); }); Java ==とequals() equals()を使用する事 == は参照が一致していれば、Trueになってしまう DOM読み込み後に処理したい場合 $(document).ready(function() { }); HTML CSS JAVASCRIPT モックJSPで画面サイズが違う場合の観点 ・form内部の値を開発者ツールでコピーしてみて一緒になる⇒自分のコードに問題あり ・フッターの二重定義 ・formのcssClass指定 ・css不足 ・javascript不足 DAOとEntityの違い データベースに、アクセスするのがDAO データベースにある、例えば「生徒」テーブルの一行がエンティティ。 エンティティは、インスタンスがされた「実体」のことを指しています。 名前、学年、性別というカラムがある生徒テーブル一行がエンティティ その一行を取り出したり、カラムを設定したりいろいろデータをごにょごにょするのがDAO HTML JAVA JSP実装注意点 基本キャメルケース? nameとFormクラスの変数名が一致していないと ボタン押下時に値が取れないらしい ボタン名を一意の名前にする ⇒ボタン毎に内部で動作が指定される可能性がある為 反省点 2016/4/28 事前調査不足の為、手戻り発生_カスタムタグ挿入 事前調査方法:既存のID、nameの付け方の方法を全検索⇒パターンから命名規約を確定 ⇒キャメルケース化、パスカルかを事前に聞くべきだった。 事前に自分たちで決められないことがないか確認 Java カスタムタグ 一つだけ改行をさせる方法 <c:set var"newLine" value="${newLine}</br>"/> 上記のようにしないとbrタグが二つ生成されてしまう 勉強の為に残しておきたいSVNのコミットを保存しておくこと プロジェクトを選択し、チーム⇒ヒストリーから、修正前後の番号を選択して エクスポートすればいい? ⇒毎日やっておかないとブランチを捨てられて見れなくなる。バッチ化? svn http://d.hatena.ne.jp/replication/20111125/1322147980 vss http://aoki1210.hatenablog.jp/entry/20080304/p1 全体 ミスを少なくする方法 修正前の既存のソース、データは消さない。 消すのはコミット直前。 全ての作業にエビデンスを エクセルで、どのバージョンのソース、資料で何を検索した結果、 何を修正することになったか、 そして修正したことのエビデンスを付ける。 2016/6/7 製造もれ 正)アコーディオンはダイアログオープン時に初期化するが、 一部のその他入力などのデフォルトで値が入ってくるものは初めからオープン状態にする 漏れた原因:作業一つ一つに対するエビデンスを作らなかった。 マトリクス(各状態におけるボタン制御等)についての具体的な実装方法 ⇒ボタン単位で処理を実装する 例)Aボタンー条件A、条件Bの場合活性。。。。 その際、すべての条件を記載数必要があるか確認する 例)Bボタンが活性になるにはAボタンが完了していてB処理が終わっていない場合 html,javascriptの基本 htmlは基本ダブルコーテーション javascript,jqueryは基本シングルコーテーション JavaScript $target.data(セレクタ)の意味 カスタムデータ属性の要素を取得する。 例)$target.data('btn-collapse') ⇒HTML上でdata-btn-collapse="aaaBtn"と指定されている場合、「aaaBtn」を取得 ⇒data-btn-collapseを設定している要素を順次取得し、aaaBtn要素内に何か変更を加えたい場合に使用 Jquery 改行コード 置換 .replace(/\n/g, '') /\n/..改行コードの場合(?)は\で始めないと文字列として判断されてしまう模様 /g...モード修飾子。該当するすべてを置換するためにこれを使う模様 ダイアログからのValidate処理法 1.親画面の編集ボタン押下 2.ダイアログ呼び出し(jsが呼び出し処理中に、押下されたボタンについてるカスタムデータ属性を保持) 3.ダイアログからsubmit(自分自身を呼ぶ)("/validate.do") 4.Controllerへ。@RequestMapping(value = "/validate.do", method = RequestMethod.POST) 5.2で割り当てた値を取り出して親画面に反映?????? Excel、VBAの基本 メソッド定義 Sub aaa() end sub 関数定義 Function aaa as String aaa = "aaa" end function 変数定義 var aaa as String 関数を使用 Worksheetfuncion.count(A1:A5) 注意点 if elseif ... else ... endif ⇒Thenのタイミングで開業してあげないとエラーになって動かない 定義又はプロパティが定義されていません ⇒必要な奴を削除しちゃった? シート内ハイパーリンク =YPERLINK("#Sheet1!A1", "aa") 画像ごと行を削除できるようにする方法 http://blog.livedoor.jp/qoozy/archives/52568172.html 吹き出しのみ削除 http://www4.synapse.ne.jp/yone/excel2010/excel2010_zu_obje_del.html bean作成時の注意点 画面で更新するものだけをBeanとして定義する ⇒何が更新されるべきものなのか、事前に明確にすべき では、ボタンの活性非活性、チェック状態制御等はSettingFormとしてModelAttributeするbeanとは分割 スクリプトレット <%= %> JSP上で部分的にセッション条件を変えたい OR 条件を変えるのが面倒な処理を一発で変える方法 正にしたい場合は後ろに || true 負にしたい場合は後ろに && false <c:if test="${hogehoge == fugafuga || true}"> 製造時に漏れがないように実装する方法 ソースファイル内に設計書の内容をすべてコピーしてから実装 ⇒余計なウィンドウ遷移をなくす Excel テキストボックスの取り消し線を追加する ホームーフォントの拡張ボタン押下 JSP BeanとJSPのマッピング 一つずつ値のセット処理を入れないと、 値が入っているかどうかわからない (メンバ名が一致しているものを自動的にコピーする方法だとわからない。エラーが出てても気づかない) ⇒BeanUtil.copyPropertiesを使うべきか問題。 改善点 作業手順 ・ヒアリングした内容をまとめる(まとめる中で気になったことは先に聞く)。作業の全量を把握する ABCがあるときに、Aはパターン1で出来るけど、Bはパターン2でしかできない、という場合が ないかどうかの把握 例)メソッド化で渡す引数について、 disabledの場合はidを設定すればid名の文字列私でも可能(オブジェクト参照でも可能) hiddenの場合はidを指定していない「tr」タグなどがたくさんある為、オブジェクト参照でしかできない ⇒disabledの場合もhiddenの場合もオブジェクト参照でないとできない javascriptで定数定義して呼び出す方法 http://d.hatena.ne.jp/MoonMtLab/20130831/1377919614 javascript 基底部分 各ソースで共通して即時関数を使用することにより、イベントの追加、基底部分の処理の呼び出しが可能。 var hoge = { app : {}, dialog : {} } (function(hoge, $) { 'use strict'; var hogeApp = hoge.app; hogeApp.hogehogee = function() { return hogeApp; } /** * HTML(DOM)読み込み後の処理 */ $(document).ready(function() { /** * イベントハンドラ */ $('.hoge').on('click', hogehogee); }); }(hoge, jQuery)); java開発時に考慮 LomBok(ロンボック) ⇒getter,setter,tostringなどの冗長コードの排除 JSP ボタンのサイズとテキストサイズがあっていない場合にボタンのどこを押してもクリックイベントが 出るようにする方法 ボタンタグを囲うdivにクリックイベントを付与 (または、jsハンドリング用のクラスをdivに設定する) JSTLで出力する場合:modelattributeから定義 <form:form modelAttribute="hogehogeForm" action="${postAction}" method="post"> <c:out value="${hogehogeFOrm.fugafugaForm.name}"/> htmlのname属性:modelattributeを省略して定義 <form:hidden path="fugafugaForm.name"/> JAVA クラス一覧をjavadocからCSVに標準出力 事前準備 環境変数にjavaのbinまでのパスを追加する 例)C:\Program Files\Java\jdk~\bin bat cd C:\workspace\testDocLet\bin javadoc -docletpath classes -doclet test.testDocLet -sourcepath 抽出したいプロジェクトパス -subpackages 抽出したいパッケージ java public final class testDocLet { public static boolean start(RootDoc rootDoc) { File file = new File("作成したいファイルのパス"); try { PrintWriter out = new PrintWriter(file); try { writeTo(out, rootDoc); if(out.checkError()) { return false; } } finally { out.close(); } } catch (IOException ex) { throw new RuntimeException(ex); } return true; } public static LanguageVersion languageVersion() { return LanguageVersion.JAVA_1_5; } private static void writeTo(PrintWriter out, RootDoc rootDoc) { // header String[] headers = new String[]{"tekitou"}); out.printin(headers); for(ClassDoc classDoc : rootDoc.classes()) { if(classDoc.name().endsWith("Form")) { for(FieldDoc fieldDoc : classDoc.fields(false)) { String[] d = new String[headers.length]; Arrays.fill(d, ""); int i = -1; d[++i] = classDoc.name(); d[++i] = fieldDoc.name(); } out.printin(join(d)); } } } private static <T> String join(T[] d ) { if(d.length == 0) { return ""; } StringBuilder s = new StringBuilder(String.valueOf(d[0])); for(it i = 1; i < d.length; i++) { d.append(",").append(a[i]); } return d.toString(); } } ??? BeanPropertyRowMapper 勉強になりそうなサイト コンピュータクワガタ 気になるjava コーティング規約 JAVA JAVA 保管アクション checkStyle javaコンパイラ設定 firebugs の設定を規約とする JAVADOC 保管アクション checkstyleの設定を規約とする 命名規約 クラス:各単語の先頭を大文字(Pascal形式)とする メソッド:各単語の先頭を小文字(Camel形式)とする 命名規約で記載する点: レイヤーなど、種類、接頭語、識別子、接尾語、例 Model、テーブル作成時(マスタ系)、M、任意の名詞(※1)、-、Mdata ※テーブル名(M_DATA)の場合 コーディング規約 JSP コメントは<%-- --%>を使用する ⇒<!-- -->だとブラウザ上でソース表示時にコメントが表示されてしまう 宣言・スクリプトレット<%= %>によるJavaプログラムの記述は極力避け(定数はOK)、JSTLを利用数 暗黙オブジェクトは極力利用しない ⇒request, response, pageContext, session, application, config, page, exception × <%= session.getAttribute("information") %> 〇 ${information} JSPファイルの先頭はコンテンツのタイプと文字コードを定義する ⇒<%@ page language="java" contentType="text/html; charset=Windows-31J"%> 共通するJSPファイルの読み込みは<jsp:include>を利用する ⇒<jsp:forward>だと呼び出し後に呼び出し側のページの実行が終了する為 定数は独自定義せずJava側で定義したものをJSPで利用する <%-- JSPファイルの上部に宣言 --%> <%@ page import="~.Constants"%> <%-- 定数を利用する --%> <c:set var="hoge" value="<%=Constants.HOGE_HOGE%>"/> <c:if test="${fuga != hoge}"> <fmt:formatNumber>の丸めモードは近似値である為、利用時には注意 ⇒あらかじめControllerクラスなどで四捨五入などの丸め処理を行ったものを渡すようにする <fmt:formatNumber pattern="#,##0" value="${suuchi}"/> HTMLタグを利用せず、Springタグを利用する http://kuwalab.hatenablog.jp/entry/20130118/p1 +form:hidden できるようになる スケルトン作成 モック作成 ⇒画面をみてHTMLを作るトレーニング? 作業の効率化 修正前の値で判定してるところを探す。判定は 合致している場合(A == B)と合致していない場合があるので、探す時は 「= 」で探す JavaScript基礎 ・等しい(===)ー同じ型に変換せず比較 ・ひとしくない(!==) 同じ型に変換せず比較しようとして等しくないか判定 html ・先頭 <!DOCTYPE html> <html lang="ja"? <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=no"> <meta name="format-detection" content="telephone=no"> ・最後 JS読み込み(パフォーマンス考慮の為) POST⇒REDIRECT⇒GET PRGパターンの実装方法 <c:url value="/パス" var="postAction" /> <form:form modelAttribute="hogeForm" action="${postAction}" method="post"> </form:form> コンテキストルート WEBアプリケーションの最上位のパス 改善点 作業確認漏れ 不具合内容、修正内容をあらかじめリーダーに連携せずにコミット ⇒あとでリーダーに指摘され修正 作業 何かをまとめてくれと言われたときの自分の対応方法 例)未実装箇所一覧 No,画面一覧,未実装箇所一覧 ⇒1セル1画面で、足りなくなったら別シートへ デメリット:足りなくなったらいちいち別シートを観なければならない タスクの割り振り入力欄が入れられない メリット:自分の入力が楽 期待値: No,カテゴリ[View,Controller,Service],画面,修正内容 ⇒1セル1修正内容 デメリット:自分の入力が面倒 メリット:そんままみんなに展開できる
■
・新規サービス作成手順 ソリューションフォルダ「Servers」を右クリックし、「追加」⇒「新しいプロジェクト」を選択する 「Vusual C#」カテゴリの「Windows」の配下にある「Windows サービス」を選び、名前を指定してOKを押下 プロジェクトのプロパティを開き、「アプリケーション」の「対象のフレームワーク」を「.NET Framework 4」 に変更する 最初にService1.csが作成されるので、デザイナで何もないところをクリックし、 プロパティウィンドウから「インストーラの追加」を選ぶ 生成されたProjectInstaller.csの"serviceProcessInstaller1"と"serviceInstaller1"から 数字の"1"を消して"serviceProcessInstaller"と"serviceInstaller"に名前を変える serviceInstallerのプロパティに以下の文字列を指定する DisplayName:サービス一覧画面に表示する名前 Description:サービス一覧画面に表示する説明。 ServiceName:サービスの識別名。プロジェクト名を指定する StartType:インストール直後のスタートアップの種類 Accout:サービスの実行アカウントの種類を選択する サービス登録(batで以下を実行) C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil C:\Service.exe pause ・バイナリ実装 16進数変換 Convert.ToByte(Convert.ToString(filever, 16), 16) BCD変換 int i,j; string s = "1001000043004865617020616E6420737461636BA5"; len = s.Length / 2; byte[] num16 = new byte[len]; j = 0; for ( i = 0; i < len; i++ ) { num16[i] = Convert.ToByte(s.Substring(j, 2), 16); j += 2; } バイナリ書き込み using(MemoryStream st = new MemoryStream()) using(BinaryWriter bw = new BinaryWriter(st)) { } using(FileStream fs = new FileStream(filePath, FileMode.Append)) { st.CopyTo(fs); } Datatable 文字列の重複削除 dataTable.AsEnumerable().Select(row => row.Field<string>("MOJIRETSU")).Distinct().Count(); 日付の重複削除 dataTable.AsEnumerable().Select(row => row.Field<DateTime>("HIZUKE").Date).Distinct().Count(); 日付の抽出 dataTable.Select("HIZUKE >= #" + DateTime.Parse("2015/08/15" + "# AND HIZUKE < #" + "2015/08/15" + "#").Count() 親子関係の考え方 A(A.1(A.1.1),A.2(A.2.2)....) 第二階層(A.1、A.2...)の数=Aの件数 更新日付が最新のものを複数テーブルの更新日付から取得 Oracle SELECT UPD_DATE FROM ( SELECT UPD_DATE FROM ( SELECT MSMR.UPD_DATE FROM TABLEA MSMR WHERE MSMR.UPD_DATE = (SELECT MAX(UPD_DATE) FROM TABLEA) UNION ALL SELECT MSMN.UPD_DATE FROM TABLEB MSMN WHERE MSMN.UPD_DATE = (SELECT MAX(UPD_DATE) FROM TABLEB) ) A ORDER BY UPD_DATE DESC ) WHERE ROWNUM = 1; 降順データ取得 Oracle SELECT T.COLUMN1, T.COLUMN2 FROM ( SELECT TABLE1.COLUMN1, TABLE1.COLUMN2 FROM TABLE1 ORDER BY TABLE1.COLUMN2 DESC ) T WHERE ROWNUM <= 2; SQL SERVER カーソル 一時テーブルに入れたデータを順次取得して、 テーブルからのデータの取得処理に使う 1.一時テーブル定義 2.一時テーブルに条件を格納(INSERT) 3.一時テーブルにカーソルセット 4.一時テーブルから順次取得した値(条件)で、テーブルからデータを取得 /* カーソル宣言 */ Declare dataCursor Cursor For Select dataType From #dataView Open dataCursor Fetch Next From dataCursor Into @dataType While @@FETCH_STATUS = 0 Begin Fetch Next From dataCursor Into @dataType End ・Excelで、アプリケーションを作成する際の注意点 Excelを常時起動させたりすると、 他のエクセルをOpen⇒Closeした際に同じインスタンスの他BookのExcelが 全て閉じられてしまい、予期せぬ状態になりかねない ⇒お客さんに別プロセスで起動させる スタートメニュー⇒「プログラムとファイルの検索」の窓に、「regdit」と入力 「HKEY_CLASSES_ROOT」⇒Excel.Sheet.12⇒Shellの上で右クリックして、 「新規」にカーソルを乗せ、「キー」をクリック 「別窓で開く」など、任意の名前を付ける 「別窓で開く」を右クリックして、同じく「新規」にカーソルを乗せ「キー」をクリックする (ここでは必ず名前をcommandと入力する事) commandを選択した状態で、右側にある「既定」をダブルクリックする "EXEのフルパス" /x "%1" と入力する https://quartet-communications.com/info/topics/21941 ・定期払い戻しの考え方 定期払い戻し額=0 SF残額 >= 手数料(手数料なしON) ※定期払い戻し能力なし、 SFのみで払い戻した方が払戻額が大きい場合 定期払い戻し額 = 0 SF残額 >= 手数料 ※定期払い戻し能力なし、 SFのみで払い戻した方が払戻額が大きい場合 定期払い戻し額 = 0 SF残額 < 手数料 ※定期払い戻し能力なし、 SFのみで払い戻した方が払戻額が大きい場合 定期払い戻し額 > 0 定期払い戻し額+SF残額 <= 手数料 ※SFのみで払い戻した方が払戻額が大きい場合 定期払い戻し額 > 0 定期払い戻し額+SF残額 > 手数料 定期払い戻し額 <= 手数料 ※SFのみで払い戻した方が払戻額が大きくなりうる場合 定期払い戻し額 > 0 定期払い戻し額+SF残額 > 手数料 定期払い戻し額 > 手数料 ※定期払い戻し含む払い戻しの方が大きくなる場合 ・Visual Studioで使用しているtrnames.oraの場所 sqlplus @? と実行して出てくるパスを指定 ・テーブル作成 Oracle 表領域(USER01)をファイル名「USER01.dbf」、100MBのサイズで作成する CREATE TABLESPACE IBKIC_DTI DATAFILE 'C:\IBKIC_DTI.dbf' SIZE 100M SEGMENT SPACE MANAGEMENT AUTO ・DB接続時に必要 Oracle <add key="DBConnectionTimeout" value="10" /> <add key="DBCommandTimeout" value="10" /> ⇒リトライ処理も ・交通系用語 飛びつき 定期外から定期区間内へ 乗り越し 定期内から定期外へ 飛びつき乗り越し 定期外⇒定期内⇒定期外 電子スターフ 車内のディスプレイ ・再現確認反省 再現確認方法見直し まずは手順通りに再現確認 そうでなければ、どのような条件なら再現するか無理やりDEBUGオードで場所を変えてもいいので再現確認する ※仮に修正済みで再現しない場合でも、 再現しうる条件を順番に提起し、 最終的にAがBに変更になったため、再現はできない旨報告する ・GYAOとABEMAの違い GYAO:CMなし、コンテンツ見放題 ABEMA:CM、プレミアム(過去視聴分) ・気づかなかった integer⇒long なるべく現地の環境に合わせて試験をする ⇒タスクスケジューラで起動される、等 数値のカンマ区切り 左寄せ、中央寄せ、右寄せ 帳票の確認方法 ⇒何が出るのか正しくて何が出ないのが正しいのかを確認する 画面と帳票の比較 帳票同士の比較 ・一部文字列抽出 =MID(D1,LEN("hogehoge") ・キャッシュクリア SQLSERVER DBCC DROPCLEANBUFERS DBCC FREEPROCCASHE ・気づかなかった 期限切れログデータ削除 非同期 列挙型の値変更 タイムアウト リトライ DB,WEBAPIからデータ取得時 outofmemory 非同期の必要性 還元データ テスト 罫線の確認 テスト 日付確認 今日以外にしてもちゃんと今日以外の日付が出るか テスト 計算式 テスト ~しながら...を変えたときに正しく変わること 計登板後_系統番号が違う場合、系統名称のみ違う場合 カレンダー画面と計上日を変更して作成ボタンを押下した場合の挙動 ⇒背景色が白なので、予約可能として処理されてしまう カレンダーは常時最新でない為、取得しに行ってエラーだった場合に どうするか⇒一件でもエラーならエラーとするか、Oracleでtnsnames.ora で接続できない ⇒datasource内を直接指定 帳票:出すものがないなら0件エラーを出す スクリプトをお客さんに出す時に注意 Use [テーブル名] go を必ず入れる ・C# Tips DBからのデータ読み出し高速化 AsNoTracking() IEnumerable<IEnumerable<Town>> towns = dbContext.Towns.AsNoTracking().OrderBy(t => t.TownID).Batch(200000); ストアド作成時の注意事項 結合したデータがNULLだった場合に、何を出すか確かめておく ⇒数値の場合はゼロ ⇒文字列の場合は~コード等 例)路線名がNULLなら路線番号 ・数値変換 16進数を10進数に変換 0x15 1*16+5 ⇒10進数 21 10進数を16進数に変換 21*16=1...5 ⇒16深栖 15 BCD 0x15 ⇒10進数 15 ・Winmergeで抜け漏れが発生しないようにする フォント:HGゴシックM 差異色:青 ・IDENTITY属性を指定している場合のINSERT // IDENTITY属性を指定している列名保持用 string indexColumnName = ""; MetadataProperty storeGeneratedPatternProperty = null; foreach(var item in entry.EntitySet.ElementType.Members) { storeGeneratedPatternProperty = item.MetadataProperties.Where(f => f.Name.Contains("StoreGeneratedPattern")).FirstOfDefault(); if(storeGeneratedPatternProperty != null && Convert.ToString(storeGeneratedPatternProperty.Value) == "Identity") { indexColumnName = item.Name; // IDENITY属性を指定された列に値を格納しても正常に動作するようにSQL文を変更 sql = string.Format("SET IDENTITY_INSERT {0} ON ", tableName) + sql; break; } } ・実行するメソッドをXMLで管理する <?xml version="1.0" encoding="utf-8"?> <TaskPool> <TaskSet TaskSeID="0001" TaskSetName="処理開始" UseFormIDs="Form1" StartTaskItemID="0001" CommonTask="false" ReportTaskNumber="1" NameSpace="Task" CardType="" PatternNames=""> <OperationJudgePool> <OperationJudge MethodID="JudgeMethod1" ErrorMessage="Err_0001" SuggestionMessage="Sug_0001" MethodComment="判定" /> </OperationJudgePool> <TaskCheckPool> <TaskCheck MethodID="CheckMethod1" MethodArg="" MethodComment="エラーリカバリ" /> </TaskCheckPool> <TaskItem TaskItemID="0001" TaskItemName="読み込み開始" UseFormID="Form1"> <Preload> <Action MethodID="Method1" MethodArg="0001" MehodComment="メソッド(0001)" /> </Preload> <Loaded /> <StatusUpdate /> <DecideMethod /> <Buton1Pushed> <Action MethodID="Transfer" MethodArg="0007" MethodComment="処理終了" /> </Buton1Pushed> <Button2Pushed /> <Leaved /> </TaskItem> <TaskItem TaskItemID="0007" TaskItemName="処理終了" UseFormID="Form2"> <Preload> <Action MethodID="Method2" MethodArg="" MehodComment="機能終了" /> </Preload> <Loaded> <Action MethodID="Method3" MethodArg="Form1" MehodComment="前画面終了" /> <Loaded /> <StatusUpdate /> <DecideMethod /> <Buton1Pushed /> <Button2Pushed /> <Leaved /> </TaskItem> </TaskSet> </TaskPool> ・Task管理用XML 埋め込まれたリソースに設定し、 名前空間を省略せずに記載するとXMLを取得できる ・DBのログを削除する方法 データベース⇒タスク⇒圧縮⇒ファイル ファイルの種類:ログ 未使用領域を解放する ・Visual Studioのビルドイベント 既にコピー先に存在する場合は失敗するので注意。 /yで上書き確認しないようにしておく必要がある copy "$(ProjectDir)log.config" "$(OutDir)log.config" /y ・変換処理 16進数文字列からbyte配列を生成 if(string.IsNullOrEmpty(str)) { return null; } int len = str.Length / 2; byte[] bytes = new byte[len]; for(int i = 0, j = 0; j < len; i++, j += 2) { bytes[i] = Convert.ToByte(str.Substring(j, 2), 16); } return (byte[]).bytes.Clone(); ・変換処理 byte配列から16進数文字列を生成 if(null == bytes) { return string.Empty; } StringBuilder sb = new StringBuilder(bytes.Length * 2); foreach(byte b in bytes) { sb.Append(string.Format("{0:X2}", Convert.ToInt32(b)); } return sb.ToString(); ・Entity Framework ストアドプロシージャの戻り値を型で取得する方法 edmxのデータベース更新でストアドを取得した後、 モデルブラウザー~、store-ストアドプロシージャ―関数インポート 列情報の取得+複合型の作成 ・C# ストアド ジェネリックス objectParameter[] para; ObjectResult<T> result = this.m_objectContext.ExecuteFunction<T>(ストアド名, para); ・list.sortの書き方 result.Sort((x, y) => x.USAGE_DATE.CompareTo(y.USAGE_DATETIME)); ・現在格納されているデ―タのINSERT文生成方法 データベースを右クリックし、メニューから[タスク]⇒[スクリプトの生成(E)。。。] データベース全体または特定テーブルのいずれかを選択して次へ 詳細選択をクリックして、スクリプトを作成するデータの種類を[データのみ]に変更する 確認画面で次へを押すと出力開始 ・Excelのキャプチャ(ヘッダ、フッタあり) PDFで保存⇒Snipping Tool ・Excel 保存時 通貨 カッコ つけさせない ExBook.SaveAs(i_saveFileName, Local:true); ・Excel 勤務時間を三等分したい場合 シリアル値を分単位に直す 分単位にした値/3を再びシリアル値に戻す ※ ・シリアル値を分単位にする方法⇒シリアル値*(24 * 60) ・分単位をシリアル値に戻す⇒シリアル値/(24*60) ・分単位にした値を/3の値を求める⇒QUOTIENT(4G8*24*60, 3) ・割り切れる値かどうか判定する方法⇒/3した結果が1かどうかで判定 ⇒ROUND(MOD($G8*24*60, 3), 0) ・sqlserverストアド インデックスを張る方法 ・実行して結果まで出るクエリ部を全選択 ・ツールバーの推定実行プランの表示を選択 ・GUI画面の中で、「不足しているインデックス」を右クリック、詳細を表示する ・インデックスのコマンドが取得できるので実行する
■
・Excel 行の高さを自動調節できるようにする補法 該当セルを選択した状態で、ホームー書式ー行の高さを自動調整 ・SQLSERVER ストアドの注意点 結合したデータがNULLだった場合に、何を出すか確かめておく ⇒数値の場合はー 文字列の場合は~コード等 例)路線名がNULLなら路線番号 ※決めておかないと、お客さんに、なんで出ないのかと説明されて面倒 ・EXCEL 罫線がどうしても引けない行の修正方法 罫線を設定したい行の下に空白用を挿入し、 機先を入力後、空白行を削除する ・SQLSERVER 他のPCでもSQLSERVERに接続できるようにする設定方法 ・構成マネージャを開く ・SQLSERVERのサービスの右ペインでSQLSERVER Browserを右クリック⇒開始 ・エクセルVBA 64bit対応 ・32bit用のVBAは保持しておく ・64bit用にするため、以下を置換 置換前:Declare 置換後:Declare Ptrsafe 置換前:Long 置換後:LongPtr ※32bitと64bitのすみわけ #if Win64 Then #Else #End If ・VBA 印刷 Public Function PrintJob(list As Variant, isPrebiew As Boolean, timeout As Integer,printer As String) { For Each data In list Set selectSheet = Worksheets(data) selectSheet.Activate Application.ActivePrinter = Get_Printers(printer) '印刷 If isPreview = False Then ActiveSheet.PrintOut flg = True Else Application.DisplayFullScreen = True Application.DisplayFullScreen = False Appllicaion.Visible = True Application.ScreenUpdating = True flg = ActiveSheet.PrintPreview(EnableChanges := False) flg = False Application.Visible = False Application.CutCopyMode = 0 End If If flg Then waitCount = 0 Do While waitCount < timeOut jobFlag = PrintJobCheck(Cells(4, CELLDATA).Value) If jobFlag Then Exit Do End If waitCount = waitCount + 1 Sleep 1000 Loop End If Next } ・VBA プリンタ名取得マクロ Public Function Get_Printers(printerName As String) Dim objWSH As Object Dim objPrinter As Object Dim sPrinterList() As String Dim sTemp1 As String Dim sTemp2 As String Dim i As Long Dim ctr As Long Dim tempPrinterName As String Get_Printers = "" Const SUB_ROOT = "Software\Microsoft\Windows NT\CurrentVersion\Devices" Set objWSH = CreateObject("Wscript.Network") Set objPrinter = objWSH.EnumPrinterConnections If objPrinter.count >= 2 Then For i = 0 To objPrinter.count - 1 Step 2 If InStr(1, LCase(objPrinter(i + 1)), LCase(printerName), vbTextComare) > 0 Then tempPrinterName = objPrinter(i + 1) Exit For End If Next End If If tempPrinterName <> "" Then sTemp1 = RegRead_API(HKEY_CURRENT_USER, SUB_ROOT, tempPrinterName) sTemp1 = Replace(sTemp1, "winspool", "") Get_Printers = tempPrinterName & " on " & sTemp1 End If Set objPrinter = Nothing Set objWSH = Nothing End Function Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _ (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, _ ByVal samDesired As Long, phkResult As Long) As Long Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" _ (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _ lpType As Long, lpData As Any, lpcbData As Long) As Long Private Const KEY_QUERY_VALUE = &H1 Private Const HKEY_CURRENT_USER = &H80000001 Declare Sub Sleep Lib "kernel32" _ (ByVal dwMilliseconds As Long) 'レジストリを開く・読み込む・閉じる Private Function RegRead_API(lRoot As Long, sSubRoot As String, sEntryName As String) As String Dim lRet As Long Dim hwnd As Long Dim sVal As String hwnd = Application.hwnd lRet = RegOpenKeyEx(lRoot, sSubRoot, 0, KEY_QUERY_VALUE, hwnd) sVal = String(255, " ") lRet = RegQueryValueEx(hwnd, sEntryName, 0, 0, ByVal sVal, LenB(sVal)) RegCloseKey hwnd sVal = Left$(sVal, InStr(sVal, vbNullChar) - 1) RegRead_API = sVal End Function ・C# タスクバーにアイコンを設定する方法 プロジェクトを右クリック⇒プロパティ⇒アプリケーションタブ⇒リソースーアイコンとマニフェスト にアイコンを設定 アイコン自体は、新規項目の追加でアイコンを作成し、アイコン用のPNG,またはICOファイルをペイントで開いて 全選択し、貼り付け。 this.ShowIcon = true; ・C# Visual Studioのアイコンのサイズを増やす方法 新規項目の追加でアイコンファイルを追加後、ダブルクリックしてデザイナ画面へ 画面中央左で右クリック右新しいイメージタイプ⇒で作成 不要なものは右クリック⇒イメージタイプの削除削除可能 ・別スレッドの処理実行方法 Application.DoEvents() ・カンマ区切り編集 3番目のカンマの値のみ取得 ^[^,]+,+[^,]+, 最初のカンマから先を削除 置換前:([^,]*),{I}.* 置換後:\1 ・カレンダー(PictureBox)カスタムコントロール ※Calendar_Init,FontData,Label_Clickイベント、ExtensionCalendar_MouseDoubleClickイベント、DayOfWeek(Enum)は別途設定する必要あり // ※Calendar_Init,FontData,Label_Clickイベント、ExtensionCalendar_MouseDoubleClickイベント、DayOfWeek(Enum)は別途設定する必要あり private const int CALENDAR_CELL_X_SIZE = 60; private const int CALENDAR_CELL_Y_SIZE = 36; private const int CALENDAR_CELL_INTERVAL_SIZE = 2; private const double CALENDAR_DOUBLE_VALUE = 1.0; private readonly int PX_SIZE = Convert.ToInt32(((CALENDAR_CELL_X_SIZE * 7) + (CALENDAR_CELL_INTERVAL_SIZE * 8) + 1) * CALENDAR_DOUBLE_VALUE); private readonly int PY_SIZE = Convert.ToInt32(((CALENDAR_CELL_Y_SIZE * 7) + (CALENDAR_CELL_INTERVAL_SIZE * 8) + 1) * CALENDAR_DOUBLE_VALUE); private readonly Color Calendar_Init = Color.Blue; private List<Label> DateLabels = new List<Label>(); private int SelectDayOfWeekOfFirst = 0; private int SelectDateCount = 0; public void init() { this.Size = new Size(PX_SIZE, PY_SIZE); // カレンダー各種初期値設定 int interval = Convert.ToInt32(CALENDAR_CELL_INTERVAL_SIZE * CALENDAR_DOUBLE_VALUE); int xSize = Convert.ToInt32(CALENDAR_CELL_X_SIZE * CALENDAR_DOUBLE_VALUE); int ySize = Convert.ToInt32(CALENDAR_CELL_Y_SIZE * CALENDAR_DOUBLE_VALUE); // ※以下は日報作成の場合 // 曜日のラベルの作成 for (int i = 0; i < 7; ++i) { Label namelb = new Label(); namelb.BackColor = Calendar_Init; namelb.Size = new Size(xSize, ySize); // 横幅の計算:| + ((1マスの横幅 + |) * ループ回数) // 縦幅の計算:| namelb.Location = new Point(interval + ((xSize + interval) * i), interval); // 任意のフォントを指定 namelb.Font = DefaultFont; namelb.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; switch (i) { // 省略してここでは日曜のみ入れている case (int)DayOfWeek.Sunday: namelb.Text = "日"; break; case (int)DayOfWeek.Monday: namelb.Text = "月"; break; case (int)DayOfWeek.Tuesday: namelb.Text = "火"; break; case (int)DayOfWeek.Wednesday: namelb.Text = "水"; break; case (int)DayOfWeek.Thursday: namelb.Text = "木"; break; case (int)DayOfWeek.Friday: namelb.Text = "金"; break; case (int)DayOfWeek.Saturday: namelb.Text = "土"; break; } this.Controls.Add(namelb); } // 日付のラベルを作成(42コ) for (int i = 0; i < 6; ++i) { for (int j = 0; j < 7; ++j) { Label lb = new Label(); lb.BackColor = Calendar_Init; lb.Size = new Size(xSize, ySize); // 横幅の計算:| + ((1マスの横幅 + |) * ループ数回数) // 縦幅の計算:((縦幅 + (| * 2) + ((縦幅 + |) * ループ回数))) // 縦幅はあらかじめ曜日を設定しているため、間隔 + 曜日分のセル + 間隔からの位置を指定 lb.Location = new Point(interval + ((xSize + interval) * j), ((ySize + (interval * 2)) + ((ySize + interval) * i))); lb.Font = DefaultFont; lb.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; DateLabels.Add(lb); this.Controls.Add(lb); // イベント生成 //lb.Click += new EventHandler(Label_Click); } } //// ※以下は月報作成の場合 //int interval = Convert.ToInt32(CALENDAR_CELL_INTERVAL_SIZE * CALENDAR_DOUBLE_VALUE); //int xSize = (PX_SIZE - (interval * 5) / 4; //int ySize = ((PY_SIZE - (interval * 4)) / 3) - 1; //// 12カ月分のラベルを作成 //for (int i = 0; i < 3; ++i) //{ // for (int j = 0; j < 4; ++j) // { // Label lb = new Label(); // lb.BackColor = Calendar_Init; // lb.Size = new Size(xSize, ySize); // lb.Location = new Point(interval + ((xSize + interval) * j), (interval + ((ySize + interval) * i))); // lb.Font = DefaultFont; // lb.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // DateLabels.Add(lb); // this.Controls.Add(lb); // lb.Click += new EventHandler(Label_Click); // lb.MouseDoubleClick += new MouseEventHandler(ExtensionCalendar_MouseDoubleClick); // } //} } // 日報 で表示できる部分を限定するためのメソッド // 前月:SelectDayOfWeekOfFirstが0未満になるまで // 今月:SelectDayOfWeekOfFirstがSelectDateCount + SelectDayOfWeekOfFirstになるまで // 来月:iBeforeLoopCount + SelectDateCountがDateLabels.Countになるまで // 日報 // ※private int SelectDayOfWeekOfFirst,int SelectDateCountは別途用意 public void GetDateInformarion(string year, string month) { DateTime selectDate; DateTime selectBeforeDate; if (DateTime.TryParse(year + "/" + month, out selectDate) && DateTime.TryParse(year + "/" + month, out selectBeforeDate)) { selectBeforeDate = selectBeforeDate.AddMonths(-1); // 指定年月の初日の曜日を取得する SelectDayOfWeekOfFirst = Convert.ToInt32(selectDate.DayOfWeek); if (SelectDayOfWeekOfFirst == (int)DayOfWeek.Sunday) { // 指定年月の初日の曜日が日曜日の場合、前月分が見れなくなる為、一週間分プラスする SelectDayOfWeekOfFirst += Enum.GetValues(typeof(DayOfWeek)).Length; } // 指定年月の日数を取得する SelectDateCount = DateTime.DaysInMonth(selectBeforeDate.Year, selectBeforeDate.Month); } } public CustomControl1() { InitializeComponent(); } protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); } ・C# 16進数文字列⇒byte配列 dataLength = dataLength / 2; binData = new byte[dataLength]; for(int i= 0; i < binData.Length; i++) { string byteData = System.Convert.Tostring(binData[i], 16).PadLeft(2, '0').ToUpper(); dataString[i * 2] = byteData[0]; dataString[i * 2 + 1] = byteData[1]; } data = new string(dataString); ・C# byte配列⇒UInt16 byte[] valueTemp = new byte[2]; Buffer.BlockCopy(value, startIndex, valueTemp, 0, valueTemp.Length); if(BitConverter.IsLittleEndian == true) { valueTemp = valueTemp.Reverse().ToArray(); } return BitConverter.ToUInt16(valueTemp, 0); ・C# byte配列⇒TelegramUInt24に設定できるUint32に変換する byte[] valueTemp = new byte[4]; Buffer.BlockCopy(value, startIndex, valueTemp, 1, valueTemp.Length - 1); if(BitConverter.IsLittleEndian == true) { valueTemp = valueTemp.Reverse().ToArray(); } return BitConverter.ToUInt32(valueTemp, 0); ・C# byte配列⇒TelegramUInt48に設定できるUInt64に変換する byte[] valueTemp = new byte[8]; Buffer.BlockCopy(value, startIndex, valueTemp, 2, valueTemp.Length - 2); if(BitConverter.IsLittleEndian == true) { valueTemp = valueTemp.Reverse().ToArray(); } return BitConverter.ToUInt64(valueTemp, 0); ・C# byte配列⇒文字列 public static string Tostring(byte[] value, int startIndex, int len) { byte[] strData = new byte[len]; Array.Copy(value, startIndex, strData, 0, len); return Encoding.GetEncoding("Shift_JIS").GetString(strData); } ・数値に変換可能な16進数文字列をHEX形式のbyte配列に変換する [size=2]20AB ⇒ 0x20-0xAB value = value.Trim(); // 指定されたサイズ分の配列を作成する Byte[] retBytes = new Byte[size]; string wkstr; // 文字列編集 if(cOrder == CharOrder.Right) { // 右寄せにする場合 // 指定した桁数になるように、左側に'0'を埋め込む wkstr = value.PadLeft(size * 2, fill); // 変換したデータは右寄せで配置 wkstr = wkstr.Substring(wkstr.Length - size * 2); } else { // 左寄せにする場合 // 指定した桁数になるように、右側に'0'を埋め込む wkstr = value.PadRight(size * 2, fill); // 変換したデータは左寄せで配置 wkstr = wkstr.Substring(0, size * 2); } // ダンプ文字列からbyte配列に変換 stringToByte(wkstr, out retBytes); return retBytes; ・年月日をBCD形式のbyte配列に変換する ※年は下二桁のみ変換する DateTime date; if(nullableDate == null) { return new Byte[3]; } else { date = (Datetime)nullableDate; } Byte[] YearBytes = GetBCDBytes(date.Year, 2); Byte[] monthBytes = GetBCDBytes(date.Month, 1); Byte[] dayBytes = GetBCDBytes(date.Day, 1); Byte[] dateBytes = YearBytes.Concat(monthBytes).ToArray(); dateBytes = dateBytes.Concat(dayBytes).ToArray(); public static Byte[] GetBCDBytes(Int32? value, Int32 size) { return GetHEXBytes(value.Tostring(), size, '0', CharOrder.RIGHT); } ・時分病をBCD形式のbyte配列に変換する if(date == null) { return new Byte[3]; } Byte[] hourBytes = GetBCDBytes(date.hour, 1); Byte[] minuteBytes = GetBCDBytes(date.Minute, 1); Byte[] secondBytes = GetBCDBytes(date.Second, 1); Byte[] timeBytes = hourBytes.Concat(minuteBytes).ToArray(); timeBytes = timeBytes.Concat(secondBytes).ToArray(); return timeBytes; public static Byte[] GetBCDBytes(Int32? value, Int32 size) { returnGetHexBytes(value.Tostring(), size, '0', CharOrder.RIGHT); } public enum CharOrder { LEFT, RIGHT } ・Word 相互参照で入れた参照を削除する方法 Ctrl + Shift + F9 ・Visual Studio デザインのラベルの枠線がつながっているところが太くなっておかしい もはやラベルを一部かぶせればつながって太くならない? ・byte配列の値を文字列に変換する byte[] encPasswd = pw.GetEncordedString(stringData); var value = "0x"; foreach(byte b in encPasswd) { value += Convert.ToString(b, 16).PadLeft(2, '0'); } ・きづかなかった ログイン用ユーザーマスタをなぜローカルDBに格納しているか ⇒遠隔DBに接続できなかったときもローカルDBに残っているDBデータでログインできるようにする為 ストアド SUM(CASE WHEN~) で条件に合致するデータのみ合計値を出せる ストアドの実行が遅いときに F5で値を取得できる状態でクエリを選択⇒推定実行プラン 出てきたGUIから不要なクエリ。。。を右クリック⇒詳細 でインデックスを張ると早くなる ・処理中ダイアログの注意点 中止ボタンを押下するタイミングが早すぎると画面が裏に隠れてしまうことがある ⇒対策:ProcessingFormの中断ボタンをEnable=falseにしておいて DispNumberLblAsync DispMessageAsync の中でtrueに変更する ・帳票確認観点1 ・Excel 列単位、行単位でExcelの関数使用部分に対し、計算結果、計算範囲、合計値が正しいことを確認する (縦、横でExcelに表示されている内容が正しいか確認する) 書式(枠線、文字コード等)があっているか、全体的に統一されているかを確認する 文字切れが出ていないかを確認する ・ストアド FROM テーブル名 ~の後の条件文は必要十分か。 ⇒FROMで検索してそのあとの条件文が正しいか判断する SELECT句:値がNULLの場合に代替案が入っているか 例)数字の場合は0、文字列の場合は''、必要な場合はCASE文 WHERE句、JOIN ON句 主キーがすべて抽出されているか 抽出字、比較する方法が正しいか 例)事業者コード+営業所のデータの時に、事業者コードまでしか比較していない GROUP BY句(~毎に一意になるように集約) 必要な箇所以上に集約されていないか 例)集約対象が多すぎると、集約したい範囲で集約されず、同じような項目が複数出力されてしまう ・全体 ストアドと帳票出力内容に差異がない事 ⇒キーの部分と実際の値がずれている、なんてことがないか確認 ストアドから取得したデータを修正し、 NULLの場合にエラーにならないことを確認する 横断的に確認が必要な項目をチェックする 例)帳票の~と画面の~は一致しているはず。。。 帳票の~と帳票~は一致しているはず。。。。 データがなかった時の挙動を確認 ⇒Excelに出力されたものの、全部金額が0円でてるようなら帳票として出す意味がない。 データがなかった時はExcel出力させないようにする ・sqlserverのオフラインがいつまでたっても終わらない sqlserver ManagementStudioの対象DBを選択し、 最新の状態に更新(F5)を選択巣rと、既に終わっているのに更新されていないだけの可能性がある ・byte配列のパスワードを文字列に変換する ⇒元に戻す処理まで入っているバージョン ※確か、GetEncordedString、GetDecodedStringはICryptoTransformかなんか使って暗号化、複合化してた様な気がする。 byte[] encPasswd = pw.GetEncordedString(txtEmployeePassword, Text); byte[] enc2 = new byte[encPasswd.Length -1]; var value = "0x"; int iCounter = 0; foreach(byte b in encPasswd) { value += Convert.ToString(b, 16).PadLeft(2, '0'); if(iCounter + 1 != encPasswd.Length) { enc2[iCounter++] = b; } } string decPasswd = pw.GetDecodedString(enc2); ・製造時懸案事項 ・DB 接続リトライ回数を設定ファイルで持つ 接続タイムアウト時間を設定ファイルで持つ クエリ実行タイムアウトを設定ファイルで持つ クエリ作成時にテーブルごとのWHEREを先にやる⇒クエリ実行時間の短縮 ・帳票 Excel-名前の定義を使用する ・ログ 期限切れログデータの削除 ・全体 非同期の要否 列挙型の値設定 タイムアウト リトライ エンコードデータ系は、正しいバイナリデータになっていることを確認する DBからのサイズの大きいデータの取得 Outofmemory ・テスト 罫線の確認 日付確認 今日以外にしてもちゃんと今日以外の日付が出るか 計算式の正否 パターン AとBは同じだがCは違う場合 カレンダー画面と計上日欄を別々の日付に変更して作成ボタンを押下した場合、どちらの値を正とするか ⇒カレンダー画面で選択していた日付の背景色が白色の項目を選択していた場合、予約可能として処理されてしまった ⇒カレンダーは常時最新でない為、取得しに行ってエラーだった場合どうするか ・仕様確認する内容 計算式⇒この計算式で正しいかの確認(間違っているもの、足りないものがあればご教示ください) ストアド⇒マッピング表を作ってこの条件でこの項目を取得する ・動的に帳票出力(同じような出力をするカタマリの数が不定) ・事前情報 ROUTE_NAME 書き込み開始場所 MAX_ROW 金庫数 TEMPLATE 書き込み開始場所から路線計までの一区分 ⇒書き込む際は行コピー先から書き込む為、 最後にこの範囲は削除される LINES 帳票データ部のすべての行数範囲。 データ部を行挿入すると範囲が変わる (カタマリの中でも行数が変わる部分をこれで管理?) ・実装:次のカタマリがあるか⇒ある⇒テンプレートをコピー挿入⇒テンプレート部分の編集⇒データ格納⇒次のカタマリ...のループ 路線別の金庫データから一つ取得 ・出力するデータがある場合 ROUTE_NAMEにLINESの最終行(行数)と、MAX_ROW(列数)から次の開始場所を登録 TEMPLATEの範囲をコピー、LINESの最終行から行コピー挿入 ・出力するデータがない場合 初回以外の場合 TEMPLATEの範囲を削除 処理終了 ・同一路線の金庫の数がMAX_ROWより大きい場合 同一路線の金庫のかずと一致するように行挿入 ⇒InsertRowColumn(ROUTE_NAME,MAX_ROW,路線ごとのDBデータ件数,ExecuteRowColType.Row) ROUTE_NAMEから順次1路線内の金庫データを格納 ・Visual Studioで~exeからインポートされた型と~の型が競合されていますと表示されるものの、 特に問題ないはずなのにクリーンしてもリビルドしても治らない場合 Visual Studioを終了後、Debugフォルダを削除し、再度起動してリビルド実行 プロジェクトフォルダー参照に不要な参照がないか確認 (自プロジェクト名が参照になぜか入っていたりしない?) ・EnvManeger(Get)のソース1 //設定項目の読み書きを同じタイミングでしないようにする private static readonly object padlock = new object(); public T GetEnv<T>(string sectionName, string key) { // ThreadSafe lock( padlock ) { string value = null; T result = default(T); TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof(T)); try { // 設定ファイルから設定管理インスタンス取得 Configration config = GetConfig(); // たぶんthisはXmlDocument SetttingElement element = this.GetElement(config, sectionName, key); // 設定値が存在する場合変換を行う if(element != null) { value = element.Value.ValueXml.InnerXml; } // 設定値が存在する場合変換を行う if(value != null) { // XMLから取得された文字列の末尾の空白と改行を取り除く value = value.TrimEnd( new Char[] { ' ', '\r', '\n' } ); if(this.UseXmlSerializer(typeConverter)) { result = this.Deserialize<T>(value); } else { result = (T)typeConvereter.ConverFromString(value); } } else { //必要なら例外をはく } } catch(Exception ex) {} return result; } } private Configration GetConfig() { string openFilename = string.Empty; // 設定管理インスタンス取得用 Configuration config = null; try { // 設定管理インスタンス取得 openFilename = setingsFilename; ExeConfigurationFileMap configFile = new ExeConfigurationFileMap(); configFile.ExeConfigFilename = openFilename; config = ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None); } catch(Exeption ex) { Logger.MainLog.Error(ex); } return config; } private bool UseXmlSerializer(TypeConverter typeConverter) { return(typeConverter == null || typeConverter.GetType() == typeof( TypeConverter) || typeConverter.GetType() == typeof( CollectionConverter ) || typeConverter.GetType() == typeof( ArrayConverter )); } ・コンフィグファイルの構成 <?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <sectionGroup name="applicationSettings" type="System.Configuration.ConfigurationSectionGroup, System.Configuration.Version=4.0.0.0" /> <setion name="Main" type="System.COnfiguration.ClientSettingsSection, System, Version=4.0.0.0" /> </sectionGroup> </configSections> <applicationSettings> <Main> <setting name="ShowPreview" serializeAs="String"> <value>False</value> </setting> </Main> </applicationSettings> </configuration> ・リリース リリース時メール記載内容 どこに格納したか 修正内容 モジュール設定補法(既存を上書きする場合・新規インストールする場合) リリースする際に、前回リリースしたモジュールがある場合はどうすればいいか書いておく ⇒~を新規fileに上書きして。。。。 ・SUMIFSを使用して結合セルの場合でも問題なく計算できるようにする方法 結合セルの中に同じ文字を入れておく方法 (結合セルが縦の場合も使用可能) 結合された状態で別シートにコピー 結合セルの結合状態を解除 結合セルの中に入れておきたい内容を結合セルの場所にコピーしておく 別シートにコピーしていた結合セルを書式コピー ・高速にExcelファイルを作成 openxml ・LDBModel.edmxの注意点 ストアドの複合型を作成する際、 一時テーブルを使用しているとうまくマッピングできない ⇒一時的にカラムを直接取得するストアドを作って読み込ませる必要がある ・LDBのソースファイル取得部分 private const string dbBaseConnectionString = @"metadata=res://*/【edmx名】.csdl res://*/【edmx名】.ssdl res://*/【edmx名】.msl:provider=System.Data.SqlClident;provider connection string=""Data Source={0};InitialCatalog={1};MultipleActiveResultSets=True;"; private const string dbTrustOption = @"Integrated Security=True"""; private const string dbRemoteOption = @"user id={2};password={3};persist securityinfo=True"""; // 認証あり string.Format(dbBaseConnectionString + dbRemoteOption, dbInstanceName, dbName, userID, password); // 認証無 string.Format(dbBaseConnectionString + dbTrustOption, dbInstanceName, dbName); *SqlConnection使用時の接続用文字列 private const string dbBaseConn_StringR = @"data source={0};initialcatalog={1};multipleactiveresultsets=True;user id={2};password={3};persist securityinfo=True"; private const string dbBaseConn_StringL = @"data source={0};initialcatalog={1};multipleactiveresultsets=True;Integrated Security=True"; ・トランザクションの張り方 using(var context = new Entities()) using(var tran = context.Database.Connection.BeginTransaction()) { try { context.テーブル名.Add(new テーブル名()); context.SaveChanges(); } catch { tran.Rollback(); } } ・sqldeveloper テーブルのスクリプト化 テーブル右クリック⇒編集⇒DDL⇒作成 ・sqldeveloper クエリの生成 メニューバーのSQLと記載されている箇所をクリックして接続先を選択 ・Zipを作成する際、フォルダーを作らないようにする方法 zip.AddFile(item, ""); のように、第二引数にから文字を指定する ・Windowsサービスその他で、SQLSERVERに以下の文言で接続できない時の対処 ”ユーザー 'NT AUTHORITYSYSTEM' はログインできませんでした” 以下を設定する コントロールパネル⇒管理ツール⇒サービス 該当サービスを右クリック⇒プロパティ⇒該当サービス名を右クリック⇒プロパティ⇒ログオンアカウント: タスクマネージャーを開き、ユーザー名に自身のユーザー名が出ているプロセスを右クリック⇒プロパティ 所有者タブの所有者英の変更欄に表示されている値を記載 パスワード:ユーザーログオン時のパスワードを指定 又は、 SQL SERVERのセキュリティ⇒ログイン⇒LOCAL SYSTEM(またはNT AUTHORITY\SYSTEM) サーバーロールタブでsysadminを追加、 ユーザーマッピングにある項目をチェックオン ・Oracle Tips コマンドライン上で、 tnsping MyDB2(tnsnames.oraに記載されているサービス名)を実行し、 名前の解決に失敗する場合 パラメータfileを使用しましたメッセージに記載されているsqlnet.oraに、 以下を設定 SQLNET.AUTHENTICATION_SERVICES= (NTS) NAMES.DIRECTORY_PATH= (TNSNAMES, EZONNECT) パラメータfileを使用しましたメッセージに記載されているsqlnet.oraと同じフォルダにある tnsnames.oraに、MyDB2(サービス名)が記載されているか確認する MyDB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = localhost) (PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = xe) ) ) DBを再起動 tnsping MyDB2(tnsnames.oraに記載されているサービス名)を実行し、 接続試行中... OKと表示されることを確認 CTLファイル例 LOAD DATA [INFILE] INTO TABLE テーブル名 APPEND FIELDS TERMINATED BY ',' ( ID, INPUT_TIME dATE "YYYY-MM-DD H24:MI:SS", IDENTIFY_KEY expression "IDENtiFY_KEY_SEQ,nextval", IS_PROCESSED CONSTRAINT 0 ) ↑INFILEにCSVのフルパスで置換する 上記は取り込むCSVにダブルコーテーションとか全部無いバージョン ・C# メソッド呼び出し用ラッパー // メソッド一覧からメソッドの呼び出し internal bool CallEventMethod(string methodID, TaskData taskData, string methodArg) { bool methodResult = false; try { Type methodPoolClass = methodPool.GetType(); MethodInfo methodInfo = methodPoolClass.GetMethod(methodID, BindingFlags.NonPublic | BindingFlags.Instance); methodResult = (bool)methodInfo.Invoke(methodPool, new object []{taskData, methodArg }); } catch(System.Exeption ex) { throw new Exception("CallEventMethod", ex); } return methodResult; } ・三角表の計算式 例) A駅 100 200 B駅 100 C駅 =INDEX(SANKAKU_RANGE,SUMPRODUCT((SANKAKU_RANGE=STATION_SRC)*ROW(SANKAKU_RANGE)), SUMPRODUCT((SANKAKU_RANGE=STATION_DST)*COLUMN(SANKAKU_RANGE))) ⇒SUMPRODUCTで条件1*行数、条件2*列数の値を取得し、INDEXでSANKAKU_RANGE内で1行目、2列目の値(100) を取得する ・Entity Framework(Oracle) private const string CONN_STR = @"metadata=res://*/【edmx名】.csdl res://*/【edmx名】.ssdl res://*/【edmx名】.msl:provider=Oracle.ManagedDataAccess.Client:provider connection string=""DATA SOURCE={0};Connection Timeout={1};"; // OS認証の場合 private const string dbOSAuthOption = @"USER ID=/"""; // SQL認証の場合 private const string dbSQLAuthOption = @"user id={2};password={3};persist security info=True"""; // SYSDBA特権の場合 private const string dbSYSDBAOption = @"dba privilege=SYSDBA;"; ※引数 query:string data:DataTable ※メンバ this.m_objectContext = new Entities(connStr); // datatableに格納 http://teruc.dnsalias.net/blog/2012/05/08/311 // 同じデータを追加する方法 data.Row.Add(data.Rows[0]); ・Oracle C# ネットサービス名の代わりに直接指定したい場合 localhost:1521/TBKTIC.test-sv ・VBA開発 バージョンによって、処理が正常に動かなくなる可能性がある CInt(Application.Version) 'バージョン番号による振り分け 例)15⇒Excel 2013 ・SQL Developer 日付書式 メニューから ツール⇒プリファレンス データベース⇒NLS YYYY-MM-DD HH24:MI:SS ・フォルダを自動的に作成するバッチ @echo off pushd %~dp0 for /f %%i in (list.txt) do mkdir %%i exit リストファイル: list.txt test\01 test\02 test\02\03 test\02\04\05 ※既存のフォルダをコピーして利用したい場合、 データごと上位階層のフォルダをコピーして、 コピーしたフォルダ内で、検索バーに「.」と打って出てきた検索結果からフォルダ以外を全削除する手もある。
■
Sprng4勉強会 脳内変換対象 Spring4勉強会 第三回 MemoValidator.java作成時に@override指定できずにエラーになる プロジェクトを選択⇒プロパティ―⇒java⇒コンパイラー⇒jdk準拠~直下のチェックボックスを外し、 コンパイラー準拠レベルを1.7にする⇒適用⇒OK 問題パースペクティブのエラーを選択⇒右クリック⇒クイックフィックスで1.7にする Spring4勉強会 第四回 pom.xmlの修正 <spring-jdbc.version>4.0.6.RELEASE</spring-jdbc.version> ~ <CommonsDbcp.version>2.1</CommonsDbcp.version> ⇒propertiesタグの中に書くこと。 <!-- MyBatis --> ~ </dependency> ⇒dependenciesタグの中に書くこと SpringTips Controllerメソッドの呼び出し戻り値=jspのファイル名 Maven javaプロジェクト管理ツール 今まで手作業で行っていたダウンロードや、プロジェクトのビルドをpom.xmlに記載することで自動化してくれる コンテキスト アプリケーションの配置場所や呼び出し方などの情報 入力値検証(Validation) 注意点 <context:component-scan base-package="jp.co.kenshu"/> ⇒ページ上ではscan baseの間が空いてないからエラーになる form:fromのmodelAttributeに指定する値と、実際にControllerでバインドさせるFormオブジェクトは名前を一致させる jsp <form:form modelAttribute="testForm"> controller TestForm form = new TestForm(); model.addAttribute("testForm", form); pathに指定する値はFormオブジェクトのプロパティ名/フィールド名と合わせる jsp <form:input path="id"/> ※<input id="id" name="id" type="text"> TestForm private int id; SpringMVCではFORMで送信される情報専用のFORMオブジェクトを用意し、リクエストオブジェクト から直接データをやり取りすることはない スクリプト言語 インタープリター言語(事前コンパイル不要言語) Spring FormタグのTips <form:form>タグ actionパラメーターを省略すると自身に飛ぶ ⇒action="/SpringKenshu/show" methodを省略した場合はPOST扱い modelAttribute="testForm"と記載すると、id属性にtestFormが指定 <form:checkboxes>タグ pathに指定するフィールドはString[]。 ⇒中にはチェック状態にしたいチェックボックスを指定する。 PRG (POST-REDIRECT-GET) redirectする場合は、「redirect:」と書いて、その後に遷移先を書くだけです。 return "redirect:/test/"; Dto(Data Transfer Object) プロセスまたはネットワークの境界を越えて転送する必要がある 集計データの集合に対する単純なオブジェクト Formクラスだと必要以上のデータを格納する為、 Formを使用してデータを管理すると、同じJSPを何度も使用する際、不要なデータを削除する処理を 入れなければならない。 DTOを使えば、必要な情報だけ格納できるし、処理効率も良くなるし、ほかの人から見てもわかりやすい 特徴: implements Serializableされる必要がある @Autowired DI(Dependency Injection) 依存性の注入 依存性:クラス間でのオブジェクトの関係している状態 注入:「外部からの設定(Configuration)」を意味 DIを使うと、プログラム中でnew(インスタンス化)することなく、 インターフェースを使って実クラスをインスタンス化します 方法: 外部(DIコンテナ)からインスタンスを注入(生成)する。xmlにその設定を記述する。 DIを導入する目的・メリット * クラス間の依存を排除する => オブジェクト間の疎結合にする。 ※ 疎結合とは、コンポーネント同士の結びつきが比較的緩やかで、独立性が強い状態のこと 緩やかにつなぐためにXMLなどの技術を利用する => そのため、変更に強い * 分業で開発しやすくなる * アプリケーションのコンポーネント(何らかの機能を持ったプログラムの部品)化を促進すること * モックツールを使って、単体テストがとてもやりやすくなる Springの構成 「src」フォルダ(開発するときはここだけ意識) ソースコードを配置します。Javaだけでなく、JSPやHTML,imgなども、この中にまとめられます。 mainフォルダ プログラム本体 resourseフォルダ xml等のリソース関係 WEB-INF 非公開ディレクトリ viewフォルダ MVCのViewが格納 「target」フォルダ アプリケーションのデータです。自動生成されます。 「.settings」フォルダ プロジェクトの設定ファイルが格納されてます。STS(Spring Tool Suite)によって作成されます。 pom.xml Mavenのビルド設定ファイルです。 Springの流れ(ざっくり) ブラウザがURLを指定してリクエストを投げる 例)http://localhost:8080/SpringKenshu/show @Controllerアノテーションがついたjavaファイルの中から、 "/SpringKenshu/show"へのマッピングが指定されたファイルを見つけ、 パッケージ名を保持 package jp.co.kenshu; リクエストに該当するマッピング指定のメソッドを呼び出し 例)@RequestMapping(value = "/show", method = RequestMethod.GET) public String showMessage(Model model){return "showMessage"} mvc-config.xmlから、先程保持したパッケージ名のノードを検索 <context:component-scan base-package="jp.co.kenshu"/> Controllerの戻り値を mvc-config.xmlのprefix,suffixと掛け合わせてjspの場所を特定、呼び出し 内部処理:(view.setUrl(getPrefix() + viewName + getSuffix());) <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> ⇒"/WEB-INF/view/" + "showMessage" + ".jsp" Springのページ作成方法 Controller作成 ・@Controllerアノテーション(メタデータ)をクラスに付与したクラスを作成 ・メソッドに @RequestMapping(value = "/hogehoge", method = RequestMethod.GET) をアノテーションを付与したString型を返すメソッドを作成 ※@RequestMapping valueを指定することで、住所を指定している。 "/hogehoge"の場合、 コンテキストルート(プロジェクト名)/hogehogeにアクセスされたときに使用する コントローラーであることをSpringに教えている ※returnする文字列は、この文字列でviewクラスを探索しにいく。 この文字列に該当するViewファイル名をフレームワークが探しにいき、あればそのテンプレートを返却するという動きをします。 ・Modelクラス ⇒Viewとの橋渡しをするためのクラス。 addAtributeはModelインスタンスに属性を追加し、内部ではsessionに値を登録しています。 第一引数には属性のkey値を、第二引数には値をそれぞれ指定します。 ⇒なぜaddAtributeしたものが画面に表示されている? 作成例) @Controller public class TestController { @RequestMapping(value = "/show", method = RequestMethod.GET) public String showMessage(Model model) { model.addAttribute("message", "hello world!!"); return "showMessage"; } } mvc-config.xmlにjspファイルとのマッピングルールを記載する 作成例) ↓はSpringKenshuプロジェクトがどこのパッケージ下をControllerとして認識するか指定している <context:component-scan base-package="jp.co.kenshu"/> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' --> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> Validation作成時の注意点 Form Integer型にはNotEmptyは指定できない。NotNullが正しい。 @NotNull private Integer age; Controller ⇒引数の先頭に@Valid(入力値検証対象オブジェクトの明示用アノテーション)を付けること 入力値を検証するオブジェクトのすぐ後ろにBindingResultを宣言すること 〇public String list(@Valid @ModelAttribute EmployeeListForm form, BindingResult result, Model model) {} ×public String list(@Valid @ModelAttribute EmployeeListForm form, Model model, BindingResult result) {} JSP BindingResultがhasErrorsの時にのみ、値を出力させる指定 <form:errors path="*" /> 「path="*"」とすることで、Formクラスの全てのプロパティを参照する。 独自Validationを作成する方法 Validation用のクラスを作成する(ここではMemoValidatorクラスとする) ConstraintValidator<Memo, String>を実体化し、 isValidメソッドで具体的なチェック処理を記載する アノテーションを自作する Validation用のクラスをインポートしたアノテーションを作成 @Constraint(validatedBy = MemoValidator.class) 日本語エラーメッセージ定義を指定する Memo={0}は文字列のみを指定してください アノテーションを付与する。 @Memo private String memo; ※validationの{0}にフィールド名ではなく、日本語名を当て込む方法 日本語エラーメッセージ定義に、このプロパティ名が来たらこのように定義する、というように変換処理を書いておく NotEmpty={0}は必須です name=名前
■
・ボタン押下時の遷移先の設定
form actionタグの中で設定
・input type(テキストフィールド)
〇 <input type="text" name="name" size=32 value="${'aaa'}"/>
× <input type="text" name="name" size=32 /><c:out value="aaa"/>
⇒テキストフィールドの外に値が出力される
・要素セレクタ css: button {color:blue;} ・クラスセレクタ css: .button {color:blue;} html: <button class="button"~></button> ・HTMLの構造に依存している ⇒div h2でcssを定義していると、 マークアップを変更したときにcssも変更しなければならない。 class名称にすればマークアップが変更になった時(div h2⇒artcle h2)に cssを変更しないで済む ・スタイルの取り消し <h2 class="title no-border">見出し<h2> ⇒titleに対してno-borderで取り消している <h2 class="title headline">見出し</h2> ⇒titleの中にborderの定義を入れず、headlineで定義することで、無駄なコードを増やさないようにする ・詳細度 !mportant インライン記述(style属性をhtmlに記載) <button style="colr:green"></button> IDセレクタ クラスセレクタ・属性セレクタ・擬似クラス [class="primary"]{color:green} class属性にprimaryだけが入っている要素を選択 要素セレクタ、擬似要素 buttton:first-child{color:green} ボタンの最初の要素に対して適用 ユニバーサルセレクタ(*) ・リファクタリング 要素セレクタを省略することで、シンプルに、メンテナンス性の高いcssにする h2.title⇒.title ul.link-list li⇒.link-list li セレクタを短くすることで、 特定の要素への依存度が減る .links li a{ display: block; } ⇒.links a{display: block;} ・セレクタ(セレクタ{プロパティ:値;}) 要素セレクタ h2 li ulとか クラスセレクタ class="aaa"のaaa 子孫セレクタ(空白を開ける) ⇒孫となる要素も含めて適用対象になる 子供セレクタ(>を使用) ⇒直下の要素のみが対象になる。 スタイルを重ねてスタイルを打ち消す必要がない HTMLタグを指定しないでクラスを選択するようにする ⇒HTMLタグを使用すると意図しない継承が発生する可能性がある 要素セレクタを省略する ⇒詳細度を高めるだけの為 セレクタを共通、個別で分ける 共通:アラート発生機能 個別:成功時、失敗時、警告時 ⇒alert success ⇒successが他と競合しない為に、successでなく、alert-successにする方がよりいい。 ・CSS LINT http://csslint.net/ ・コンテナとコンテンツを分離 場所に依存しないセレクタを書く ⇒#header .logo{} #footer .logo{} ⇒.logoとしてまとめる そして、共通から変更されるものが出てきたら、 logo small-logoのように、 必要なプロパティのみ拡張するようにする 1.ヘッダーとフッターのロゴ ⇒内容が同じなら共通の.logoとして定義 2.フッターのロゴだけ小さいロゴにしたい ⇒必要なプロパティのみ拡張したcssを作る ・まずは継承等考えずに書いてみる ・幅の情報を拡張元に持たせない .btn{...} .btn--short{width:200px;} .btn--long{width:480px;} .btn--full{width:100%;} <button class="btn btn--long">~</button> <button class="btn btn--full">~</button> ⇒ただ、これだと例えばshortとlongの間ができたときにその都度悩む 実際は、divごとに幅が異なる場合が多いため、 ブロック(div等)に幅を持たせることも考える css: form__button{width: 200px; /* フォームにおけるボタンの幅 */ } html: <div class="form__buton"> css: comment__button{width: 120px;} html: <button class="btn comment__button"></button>