■
・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>
文系プログラマが問題を解決するまでの思考回路_はじめてAzure触ってみた編
遅ればせながら、Azureを使用してみようと思い立ち、
ネットに転がっている情報から、
以下のサイトにたどり着いて、一通りAzure上で動くところまでやってみた。
やってみた感想としては、
大部分は、そのまま流れに沿ってやればできた。
が、最後にハニートラップに阻まれた。
(ブログの方はきっと悪くない。当時は動いたのだろう。)
ローカルでWebApplicationをスタートアップに設定し、
実行するところまでは何とか行けたが、
一番最後の
「Azure上で動作確認」
が、どうしても失敗してしまっていた。(502 Bad Gateway ...)
これを解決するのに結局一日かかった。
どうやら、GoogleAPIの認証をするための証明書がうまく作れずに
エラーになってしまっているらしい。
ということで、一行ソースを書き換えたらうまくいった。
var certificate = new X509Certificate2(analyticsKeyFile, "notasecret", X509KeyStorageFlags.Exportable);
⇒
var certificate = new X509Certificate2(analyticsKeyFile, "notasecret", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
因みにこんなサイトを参考にしました。
どうすればもっと早く解決できたかなー。
ここからは文系プログラマがどういう思考回路で解決まで至ったか、
参考にして頂ければと思います。
こう考えていればもっと早かったんじゃない!?とか助言を頂けるとすごく嬉しい。
自分の解決までの道のり
3/12 17:00 エラーが出てTwitterに連携されない。
3/12 17:00 ~ 21:00
⇒エラーの内容で検索をしてみるが、いい解決策が見つからない
3/12 22:00 ~ 08:00
⇒ふて寝
3/13 08:00 ~ 11:00
⇒作者のGitからソリューション取得、Azureに上げてみると一度成功(?)
3/13 11:00 ~ 14:00
⇒自分のソースと作者のソースコードの差分を必死でなくそうとする
(app.config,web.config,参照dllのバージョン、.Net Frameworkのバージョン。。。。)
⇒でもやっぱりうまくいかない。もう一度作者のソリューションでAzureに上げたやつ
を動かしてみる→動かないやんけ!!
(T-T)
3/13 14:00 ~ 16:00
⇒「C# Azure 502」とかでGoogleさんに聞いても解決せず。
(もういいよ。。。どうせ自分にはプログラミングのセンスがないんだろ。。。)
3/13 16:00 ~ 17:00
⇒作者のブログに、Google AnaliticsはB1 Basicプラン以上じゃないと動かないという
記述を見つけ、無料試用期間の自分にはそもそも動かせなかったプログラムじゃない
かとあきらめつつ検索
(ここまで来たら明日まで粘ってやっからな。。。覚悟しとけAzureさんよぉ!)
⇒「azure google analytics」で検索してたら、
認証時にAzureがうまく動いてくれてない(?)という記事を見つける
⇒StackOverFlowの記事を見つけて適用してみたら動いた
\(T_T)/
今日はみんなよい休日を過ごせたでしょうか。
プログラミングの環境構築Tips
・本に書いてある環境構築方法を実践するときには、
バージョンは「かならず」同じものを使用する。
(セキュリティー面で最新のものを…、バグが治ってるかもしれないからとりあえず最新を…とかやってるとバージョン差異でうまく動かくなることが多い)
・ruby on rails(windows 8.1 64bit時)
ruby on rails4 アプリケーションプログラミングを読みながら環境構築した際、
以下のエラーが出て詰まった。
C:/Ruby200/lib/ruby/gems/2.0.0/gems/tzinfo-1.2.2/lib/tzinfo/data_source.rb:182:i
n `rescue in create_default_data_source': No source of timezone data could be fo
und. (TZInfo::DataSourceNotFound)
解決方法:
C:\data\railbook\Gemfileをメモ帳などのテキストエディタで開き、
一番下に、
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw]
を追記。
コマンドプロンプトでその後、以下のように実行
c:\data\railbook>bundle update
c:\data\railbook>rails server
教えてくれたブログに感謝。
■
Convert.ToByte(DateTime.Now.Year.ToString().Substring(0, 2)); System.Text.Encoding.ASCII.GetBytes("Penguin",0,7,d.name,0);
dt.Rows[0][0]
dt.Select("UPD_DATE >= #2015/07/24#").Length