スマホに貼っているガラスフィルムを交換するときのはがしかたです。

薄いカード上のものをフィルムの隙間にゆっくり差し込みます。

IMG_0019

カードを中心部に向かって押し込みながらぐるっと一周まわすときれいにはがれます。
フィルムを無理に持ち上げようとすると、フィルムにヒビが入ったり割れたりする恐れがあるので注意してください。

IMG_0020

差し込むカードは、本体側のパネルを傷つけないためにも、あまり硬いものではなく紙製でプラスティックコーティングしてあるようなすべりの良いものが適していると思います。

Visual Studio 2019でフォントの変更が行えなくなりました。

前日まで問題なくカスタマイズした状態で好みのフォントが表示されていたのに、今朝立ち上げたときから知らないフォント(おそらくCourier New)に変わっています。

解決までにけっこう時間がかかったので試したことを記録として残します。

Read More

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分強で処理できました。

Read More

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: ネットワーク接続が切れました。」と表示された場合

ESETのファイアウォール機能を停止しコミットを行ってみると、先ほどまでの状態が嘘のようにあっさりと解決。問題なくコミットされました。

今回もmacOSのESETが原因でした。

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ファイル)を探し、ブックに含まれるシートの選択セルの位置や表示倍率などを一括設定できるプログラムを公開します。

2020-10-29 (2)

このツールでできること

  • ブックに含まれるすべてのシートの選択セルをA1(一番左上のセル)にする
  • ブックに含まれるすべてのシートの表示倍率をそろえる
  • ブックに含まれるすべてのシートの印刷時に横方向のページ数を設定する
  • ブックの選択シートを最初のシートにする
  • ブックの全シート(可視化されているシート)を指定ディレクトリにPDFエクスポートを行う

「印刷時に横方向のページ数を設定する」機能は、シートで使用しているカラム数に応じて拡大縮尺率を決定するExcelの機能をより便利に使用できるようにします。
設定値に「1」を設定しておくことで横方向の見切れを防ぐことができます。

Excelで記述された大量の仕様書を受け取り個々の内容を確認する必要があるが中に含まれるワークシートの設定がバラバラ、印刷をするためには一度ブックを開き手動で印刷設定しなければならないといった場面で省力化が期待できると思います。
また、電子ノートなどで閲覧するためにPDFに変換する必要があるといった場面でも使えるようExcelのPDFエクスポート機能を使ってPDFファイルの一括出力もできるようにしています。

Read More

2011年にEAP業務支援システムに関する記事で「ジェノグラム作成機能の強化をはじめました」と記事を書きましたが9年経ってようやく形になりました。

Adobe Flex(Apache Flex)で記述した以前のバージョンでは試作品までは作ったもののシステムに組み込むには十分な機能を実装できず凍結状態に。
今回Windowsの.NET上で動作するものを開発しました。

2020-10-25 (5)

JetBrains社のPython開発環境『PyCharm』を使っているのですが、アップデートかアップグレードをしたあたりから起動中に以下のような画面が表示されて起動しなくなってしまいました。

2020-10-16

実は、この現象には過去何度か遭遇し都度対応しているのですが、次に遭遇したときには前回の記憶がきれいさっぱりなくなっていて最初から調べ直しになっています。
(記憶が不確かながら『PyCharm』だけでなく『DataGrip』や『IntelliJ IDEA』など他のJetBrains製品でも発生しているように思います)
今回未来の自分のために書き残しました。

Read More

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);
		}
	}
}