WPFで、あるウインドウから子ウインドウを開き、子ウインドウが閉じたときに元のウインドウにフォーカスが戻らないという現象に遭遇しました。
この現象をネットを検索してみると以前からある問題のようでいろいろな解決方法が提案されていました。
その中からいくつかの方法を試してみたのですが、残念ながら期待通りに動きませんでした。
自分が試してみてうまく機能した方法を紹介します。
public void ForceActivate() { this.Activate(); System.Threading.Tasks.Task.Run(async () => { await System.Threading.Tasks.Task.Delay(100); Dispatcher.Invoke(() => this.Focus()); }); }
Task.Delayメソッドを使って処理をずらすよう工夫したのが効いているようです。
最初はDispatcher.Invokeメソッドのアクションデリゲート内で定番のTopmostプロパティをtrue、falseの順に設定するなども含めていたのですが、ディレイをかけてFocusメソッドを呼び出すだけで良いようです。
xxx.xxx.xxx.xxx形式のIPアドレスから国名を調べる作業をしているとき面倒になって作った関数です。
Excelシート内でユーザ定義関数として使用、またはVBA内で使用することができます。
https://software77.net/geo-ip/ より取得したデータをVLOOKUP関数で拾っているだけですが、データベース上に記載されていない127.0.0.1など予約済みアドレスを関数内でチェックして、該当する場合、適当なネットワーク名を返すようにしています。
手元のマシンでは100万件のデータを2分強で処理できました。
macOS上の環境でApache HTTP Serverのmod_dav_svn経由でSubversionに大量のファイルをコミットしようとしたところ、下記のようなエラーがApacheのログに記載されていました。
(70007)The timeout specified has expired: [client XXX.XXX.XXX.XXX:XXXXX] An error occurred while reading the request body (URI: リポジトリ上のファイルパス) [XXX, #0]
(70008)Partial results are valid but processing is incomplete: [client XXX.XXX.XXX.XXX:XXXXX] An error occurred while reading the request body (URI: リポジトリ上のファイルパス) [XXX, #0]
ファイル名を確認すると少し大きめのファイルをコミットしようとしたタイミングで問題が発生しやすいようです。
そこで、Apacheの設定パラメータのデフォルト値が変更されたことに伴うものかと思いRequestReadTimeoutディレクティブやLimitRequestBodyディレクティブの値を、
RequestReadTimeout header=0 body=0
LimitRequestBody 0
のように変更してみました。
この処置で、一部分はコミットが通るようになったもののスッキリと完全解決までは至りません。
そもそも「少し大きめのファイル」と書いたもののWindows環境からはもっと大きいファイルが問題なくコミットできています。
「じゃあSubversionのクライアントが古いことが原因か?」と考えてもファイルによっては問題なくコミットできています。
ログのメッセージで検索してみると、自分が解決方法を書いていました。
『ブラウザのコンソールに「net::ERR_CONNECTION_RESET」「Failed to load resource: ネットワーク接続が切れました。」と表示された場合』
SQL ServerのバックアップをAccess形式で取り、そのバックアップを別のSQL Serverに流し込もうとしたのですが、SQL Server Management Studioではデータ型の問題などで単純に流し込むことができませんでした。
そこで、バックアップを取ったAccessファイルに流し込みたいSQL Serverへのリンクテーブルを作成しデータ型の変換などの問題をAccessにまかせてデータを流し込むことにしました。
このスクリプトはSQL Serverへデータを流し込む作業を省力化するために作成したものです。
Accessのメニューから『データベースツール』-『Visual Basic』でVBAの編集画面を開き、適当な『標準モジュール』に下記のソースを貼り付けます。
VBA編集画面の『実行』-『Sub/ユーザーフォームの実行』から実行、またはイミディエイトウインドウで『CopyData』と入力しENTERキーで実行します。
テーブルのプレフィクス部分(スキーマ名)を変えればPostgreSQLなどSQL Server以外のデータベースでも使用できると思います。
Option Compare Database Option Explicit ' リンクテーブルにつけられるプレフィクス(スキーマ名) Const TABLE_PREFIX = "dbo_" '------------------------------------------------------------------------ ' Accessのデータをリンクテーブルに流し込むスクリプト '------------------------------------------------------------------------ ' ' コピー元とコピー先のテーブル構造が同じ(項目名が同一、データ型は互換性が ' ある型)であること、ベースとなるテーブル名が同じでコピー先のテーブル名には ' プレフィクスが付いていることを前提とする ' ' 例) テーブル『M_社員』 ' ' コピー元(Access): M_社員 ' コピー先(SQL Server): dbo_M_社員 ' ' Accessのテーブル群の中からプレフィクス付きのテーブルを探し、プレフィク ' スを取り除いたテーブルをコピー元としてSQL文「INSERT INTO コピー先 ' SELECT * FROM コピー元」を実行する ' Sub CopyData() Dim tbl As TableDef Dim name As String Dim sql As String For Each tbl In CurrentDb.TableDefs If Left(tbl.name, Len(TABLE_PREFIX)) = TABLE_PREFIX Then 'ベースのテーブル名を決定 name = Mid(tbl.name, Len(TABLE_PREFIX) + 1) Debug.Print (name) ' コピー先テーブルの現在のデータを削除 sql = "delete from " & tbl.name Debug.Print (vbTab & sql) CurrentDb.Execute (sql) ' コピー元からコピー先へデータをコピー sql = "insert into " & tbl.name & " select * from " & name Debug.Print (vbTab & sql) CurrentDb.Execute (sql) End If Next End Sub
指定されたディレクトリ下にあるExcelファイル(.xlsxファイルまたは.xlsファイル)を探し、ブックに含まれるシートの選択セルの位置や表示倍率などを一括設定できるプログラムを公開します。
「印刷時に横方向のページ数を設定する」機能は、シートで使用しているカラム数に応じて拡大縮尺率を決定するExcelの機能をより便利に使用できるようにします。
設定値に「1」を設定しておくことで横方向の見切れを防ぐことができます。
Excelで記述された大量の仕様書を受け取り個々の内容を確認する必要があるが中に含まれるワークシートの設定がバラバラ、印刷をするためには一度ブックを開き手動で印刷設定しなければならないといった場面で省力化が期待できると思います。
また、電子ノートなどで閲覧するためにPDFに変換する必要があるといった場面でも使えるようExcelのPDFエクスポート機能を使ってPDFファイルの一括出力もできるようにしています。
2011年にEAP業務支援システムに関する記事で「ジェノグラム作成機能の強化をはじめました」と記事を書きましたが9年経ってようやく形になりました。
Adobe Flex(Apache Flex)で記述した以前のバージョンでは試作品までは作ったもののシステムに組み込むには十分な機能を実装できず凍結状態に。
今回Windowsの.NET上で動作するものを開発しました。
Java 7から導入されたjava.util.Objects#equalsを使うと2つのオブジェクトが等しいか簡単に評価できるようになりました。しかし、特定のプロパティを除き2つのオブジェクトが等しいか評価する用途には使えなかったので書いてみました。
引数obj1と引数obj2のどちらもnullの場合は同じ、どちらか片方だけがnullのときは同じではないと評価します。それ以外の場合はプロパティごとにjava.util.Objects#equalsを使って評価します。
import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collection; import java.util.Objects; public class BeanCompare { /** * 2つのBeanに含まれるプロパティを比較し同一か判定する。 * 比較の際、excludeProperiesで指定されたプロパティ名は対象から除外する * * @param <T> Beanの型 * @param obj1 比較する1つめのBean * @param obj2 比較する2つめのBean * @param excludeProperies 比較から除外するプロパティ名 * @return trueのとき一致 * @see java.util.Objects#equals(Object, Object) * */ public static <T extends Serializable> boolean equals(T obj1, T obj2, Collection<String>excludeProperies) { if (obj1 == null && obj2 == null) { return true; } if (obj1 == null || obj2 == null) { return false; } try { BeanInfo bi = Introspector.getBeanInfo(obj1.getClass()); PropertyDescriptor[] pds = bi.getPropertyDescriptors(); for (PropertyDescriptor pd:pds) { if (excludeProperies.contains(pd.getName())) { continue; } Method getter = pd.getReadMethod(); Object val1 = getter.invoke(obj1); Object val2 = getter.invoke(obj2); if (!Objects.equals(val1, val2)) { return false; } } return true; } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException(e); } } }
JavaのJAX-RSと.NETのAutoRest/Microsoft.REST.ClientRuntimeを使ってRESTを使った連携プログラムを書いているときに、日付データ(JSONのtype=”string” format=”date-time”やformat=”date”なデータ)のシリアライズ/デシリアライズが初期状態では意図したとおりに動かないことがあったので、カスタマイズしたデシリアライザを書いた時のメモです。
.NET環境からのメール送信について、検証用にいくつかの方法を試したときのメモです。
送信先のメールアドレス、件名、本文が設定された状態でWindowsの規定のアプリで設定されているメーラーが起動します。
この方法ではメールの送信を行うことはできませんが、たった1行で編集画面に最低限の初期値を流し込むことができるので便利です。
CCやBCCも「&cc=《CC先メールアドレス》」「&bcc=《BCC先メールアドレス》」とパラメータをつなげることで設定可能です。
System.Diagnostics.Process.Start("mailto:" & 《送信先メールアドレス》 & "?subject=" & Uri.EscapeDataString(《件名》) & "&body=" & Uri.EscapeDataString(《本文》))
WindowsにインストールされているOutlookを使いメールを送信します。
送信に使用するメールサーバなどの設定はOutlookで設定されているものを使用し、送信したメールはOutlookの『送信済みアイテム』に残るので便利です。
Dim app As Object Dim item As Object app = CreateObject("Outlook.Application") item = app.CreateItem(0) ' 0 = OlItemType.olMailItem item.To = "《送信先メールアドレス》" item.Subject = "《件名》" item.Body = "《本文》" item.Send() app.Quit()
MailKit( https://github.com/jstedfast/MailKit )を使いメールを送信します。
MailKitはNuGet経由などであらかじめインストールされている必要があります。
この方法は、依存するライブラリやソフトが非常に少なく.NET Coreでも使用可能です。また、送信に関する多くの項目を自分で設定できるので便利です。
Dim mimeMessage As New MimeKit.MimeMessage mimeMessage.From.Add(New MimeKit.MailboxAddress("《送信元氏名》", "《送信元メールアドレス》")) mimeMessage.To.Add(New MimeKit.MailboxAddress("《送信先氏名》", "《送信先メールアドレス》")) mimeMessage.Subject = "《件名》" mimeMessage.Body = New MimeKit.TextPart(MimeKit.Text.TextFormat.Plain) With {.Text = "《本文》"} Using client As New MailKit.Net.Smtp.SmtpClient() client.Connect("《SMTPホスト》", 《SMTPポート番号》, MailKit.Security.SecureSocketOptions.Auto) client.Authenticate("《SMTPユーザ名》", "《パスワード》") client.Send(mimeMessage) client.Disconnect(True) End Using