仕事でAccess2010でのシステム開発をしているのですが、ちょとぉ、ちょっと、ちょっとというのに気づきました。
まぁ、今のところ致命的な実害があったわけではないのですが、ちょっと気になる点の指摘を。
テーブルのデザインの時のフィールドのプロパティや、フォームデザインのプロパティシートの書き換えが遅いのです。
Windows7(Windows8系を真面目に使ってなかったので)では、何も気になりませんでしたが(というか、人が気になるほどの遅さでなかったって言うこと)、Windows10では、カーテンが閉まるようにスーっとゆっくりと白くなって、パッっと表示されるのが目に見てわかるようになりました。
フォームのプロパティシートの場合、プロパティの一つ一つでフォーカス移動するだけで、書き換えているのがわかります(ちらつく)。
今のところアプリケーションの実行で問題が起きているわけではないのでちょっと我慢できますが、アプリケーションの動きで問題が出始めたら、Windows7に戻ります。実際は、Access2010の開発の時だけですけどね。
別のPCにインストールしたWindows7かVHDブートできるよにしたWindows7のどちらかですけどね。
やっぱり開発者は、VHDブートできるWindowsを環境毎に持っているといいかもしれませんね。
新潟市で個人でコンピュータ相手にシステム開発をしています。確実、安く、素早くをモットーにやっています。
システム開発の時に調べた技術を惜しみなく公開していきます。あまりよろしくない業者についての苦言も為に吐きます。
コンピュータにベッタリというのもどうかと思いますが、やはりこれからは、コンピュータのことを知らないよりは知っていたほうが良いと思いますよ。
2015年8月24日
2014年2月23日
Accessで既存テーブルにフィールドを追加する方法
Accessのシステムを作るときは通常(絶対ともいう)、アプリケーション部分とデータ部のファイルは分けて作ると思います。
で、リリースしたアプリケーションがバグっていたり、機能強化をする時にテーブルに列を追加したりすると思いますのでその方法をメモ。そして解説。
仕様
これだけわかれば、VBAを使ってテーブルのレイアウトを自由に変更することができるようになると思います。
アプリケーションを変更したいだけなのに、既存データを新しいところにインポートするとかいうわけのわからない作業はしなくても良くなります。
※チョット前に引き継いだAccessのアプリケーションがそんなのでした。
テーブルのデータをエクスポートやインポートで移行するならまだしも、CSVファイルに出力して移行するというアホな設計でした。
で、リリースしたアプリケーションがバグっていたり、機能強化をする時にテーブルに列を追加したりすると思いますのでその方法をメモ。そして解説。
- Dim def As DAO.TableDef
- Dim fld As DAO.Field
- Dim prp As DAO.Property
- Set def = CurrentDb.TableDefs("なんとかテーブル")
- With def
- .Fields.Append .CreateField("メモ", dbMemo)
- Set fld = .CreateField("一括更新", dbBoolean)
- .Fields.Append fld
- Set prp = fld.CreateProperty("Format", dbText, "Yes/No")
- fld.Properties.Append prp
- Set prp = fld.CreateProperty("DisplayControl", dbInteger, acCheckBox)
- fld.Properties.Append prp
- End With
仕様
- 既存のテーブルに対して"メモ"フィールド(メモ型)、一括更新フィールド(ブール型)の列を追加する。
- ブール型の列の表示は、チェックボックスにする
解説
- 5行目:変更するテーブルのTableDefオブジェクトを取得する。
- 7行目:新しいフィールドを追加する
TableDefオブジェクトには、CreateFieldというメソッドでフィールドオブジェクトを作成し、FieldsプロパティのAppedメソッドで追加する。
列を追加するだけだったらこれだけで終わり。 - 8~13行目:フィールドの追加とそのフィールドのフォーマットや表示形式を指定する。
- 8~9行目:7行目と同様ですが、新しく追加するフィールドに対してプロパティを追加したりするので変数に格納する。
- 10行目:テーブルデザインの書式をプロパティオブジェクトに定義します。
※他にも表題、規定値、入力規則、エラーメッセージ、インデックス、文字配置などがありますね。
引数説明
第1引数:書式の英語名を指定する。書式の場合は、Format。
第2引数:プロパティの値のデータ型を指定する。第3引数には、"Yes/No"という引数を指定するので、dbText。
第3引数:設定する値を指定する。テーブルデザインで選択する値をそのまま記載。 - 11行目:できたプロパティオブジェクトを8行目で作成済みのオブジェクトのPropertiesプロパティにAppendメソッドで追加します。
- 12~13行目:テーブルをデータシートビューで見た時に、チェックボックスになるようにするための設定です。
- 12行目:10行目のルックアップタブ内の値を指定します。
第1引数:書式の英語名を指定する。書式の場合は、Format。
第2引数:プロパティの値のデータ型を指定する。第3引数には、acCheckBoxという整数型の定数を引数を指するので、dbInteger。
第3引数:チェックボックスにシたいので、acCheckBoxを指定する。
※他にも、acTextBox、acListBox、acComboBoxというのが有ります。
アプリケーションを変更したいだけなのに、既存データを新しいところにインポートするとかいうわけのわからない作業はしなくても良くなります。
※チョット前に引き継いだAccessのアプリケーションがそんなのでした。
テーブルのデータをエクスポートやインポートで移行するならまだしも、CSVファイルに出力して移行するというアホな設計でした。
2014年2月17日
Access2010のレポートのバグ?並び順が変わる!
本日、リリースしたAccess2010のレポートで印字明細のソート順が変わってしまうという現象にあってしまいました。
前回リリースした時は、確実にこのプロパティには、並べ替えをする項目が設定されていたのですが、今回リリースしたレポートはクリアされていました。
自分でクリアした記憶はないので何が原因かを調べたところ発見しましたよ。
【操作】
【問題点】
レポートのプロパティの「並べ替え」の内容が空になっている。
レコードソースにクエリを指定しているのですが、そのクエリのデザイナをプロパティから開いて閉じる(保存しなくても)と並べ替えの項目がクリアされてしまうようです。
Access2010は、勝手にプロパティを変更してしまう可能性があるのでちょっと注意が必要かもしれません。
もしかするともう既にバグフィックスされているかもしれませんが。
前回リリースした時は、確実にこのプロパティには、並べ替えをする項目が設定されていたのですが、今回リリースしたレポートはクリアされていました。
自分でクリアした記憶はないので何が原因かを調べたところ発見しましたよ。
【操作】
レポートのプロパティのレコードソースを開いて閉じる。
【問題点】
レポートのプロパティの「並べ替え」の内容が空になっている。
レコードソースにクエリを指定しているのですが、そのクエリのデザイナをプロパティから開いて閉じる(保存しなくても)と並べ替えの項目がクリアされてしまうようです。
Access2010は、勝手にプロパティを変更してしまう可能性があるのでちょっと注意が必要かもしれません。
もしかするともう既にバグフィックスされているかもしれませんが。
2013年12月19日
Access97でモジュールを変更すると落ちる
Access97(無印)でアプリケーションを作成して完成後にモジュールをちょっといじるとAccess自体が異常終了することがあります。
(モジュールをコンパイルしても異常終了する場合があります)
原因は完全に不明です。
OSの再起動等いろいろしてみても絶対に改善しません。
Access自体のバグというのは間違いないと思うのですが、Access97自体もう既にサポート切れなのでマイクロソフトも何もしてくれません。
本来は、Access97は使用せずにバージョンアップすれば良いのですが、ユーザの都合でそうも行きません。
で、復旧させる方法を考えましたので一応記録しておきます。
もし、困っている方は試してみてください。
(モジュールをコンパイルしても異常終了する場合があります)
原因は完全に不明です。
OSの再起動等いろいろしてみても絶対に改善しません。
Access自体のバグというのは間違いないと思うのですが、Access97自体もう既にサポート切れなのでマイクロソフトも何もしてくれません。
本来は、Access97は使用せずにバージョンアップすれば良いのですが、ユーザの都合でそうも行きません。
- モジュール以外のオブジェクトを新しいmdbファイルにエクスポートする。
(モジュールは新しく作るため、モジュールはそのまま) - 1.で作成したmdbをAccessで開き、新しいモジュールを作成します。
- 2.で作成したモジュールに、1.のモジュールのソースの内容をコピー&ペーストします。
(モジュールの数分繰り返します。) - モジュールをコンパイルします。
もし、困っている方は試してみてください。
2013年12月3日
Accessの追加クエリーで連番を振る
Accessの追加クエリーで連番を振る方法を説明します。
この機能を使うことで、VBAでゴリゴリとコーディングする必要なく数行のコーディングで簡単にレコードをコピーしながら連番を振ることができるようになります。
この機能を使うことで、VBAでゴリゴリとコーディングする必要なく数行のコーディングで簡単にレコードをコピーしながら連番を振ることができるようになります。
要件
入力テーブルから出力テーブルへレコードこコピーする時に、出力テーブルの項目に連番を振りたい。作るもの
- 連番を発行する関数
- レコードコピーする追加クエリ
- 追加クエリを実行する
連番を発行する関数
標準モジュールに関数を準備します
Dim newNum As Long
' 連番を初期化する
' GetNewNumを実行する前に呼び出す。
Public Sub InitNum()
newNum = 0
End Sub
' クエリ内で呼び出す関数。
Public Function GetNewNum(v As Variant) As Long
newNum = newNum + 1
GetNewNum = newNum
End Function
レコードをコピーする追加クエリ
連番を振りたいフィールドに「連番:GetNerNum([フィールド1])」のように記載します。
このフィールド1は、入力テーブル内にフィールド名を指定します。(値がnullにならない項目を指定します。)
追加クエリを実行する
クエリを実行する前に「InitNum」を呼び出して連番の初期値を設定します。
(これを実行しないと何が)
Private Sub 実行_Click()
Dim qDef As QueryDef
Call InitNum ' 連番を初期化する
Set qDef = CurrentDb.QueryDefs("QIテーブルコピー")
qDef.Execute
qDef.Close
End Sub
2013年9月4日
Accessのトランザクションにハマるの巻
人から引き継いだMS Accessのプログラムで外部ファイルをテーブルに取り込んで処理をするというよくあるプログラムのバグ調査をしている時にトランザクションに関わるプログラムのバグに悩まされた。
トランザクションを開始してから、入力ファイルがないのでそのサブルーチンをを抜けるというロジックがありました。
で、トランザクションを閉じず(Commitとか、Rollback)にサブルーチンを抜けているもんだから、次のサブルーチンでトランザクションを開始してテーブルにレコードをいくら登録して、全然登録されないという気持悪い現象に大ハマリでした。
1)トランザクション開始(BeginTrans) ← これをちゃんと閉じないのが問題!
↓
2)トランザクション開始(BeginTrans)
↓
3)レコードをINSERTを繰り返す
↓
4)Commit
↓
5)終わり
1)のトランザクションがかかりっぱなしなので、4)でコミットをしてもデータは登録されずにそのまま。
Accessは、Workspaceに対してトランザクションをかけるのですが、同じワークスペースには、1つしかトランザクションをかけられないので、1)のトランザクションは、かかっているけど、触りようがないトランザクションになっているのです。
開けたら、閉める。これ当たり前の動作。皆さん気を付けましょう。
これでやっと、本当のバグ調査ができますよ。
トランザクションを開始してから、入力ファイルがないのでそのサブルーチンをを抜けるというロジックがありました。
で、トランザクションを閉じず(Commitとか、Rollback)にサブルーチンを抜けているもんだから、次のサブルーチンでトランザクションを開始してテーブルにレコードをいくら登録して、全然登録されないという気持悪い現象に大ハマリでした。
1)トランザクション開始(BeginTrans) ← これをちゃんと閉じないのが問題!
↓
2)トランザクション開始(BeginTrans)
↓
3)レコードをINSERTを繰り返す
↓
4)Commit
↓
5)終わり
1)のトランザクションがかかりっぱなしなので、4)でコミットをしてもデータは登録されずにそのまま。
Accessは、Workspaceに対してトランザクションをかけるのですが、同じワークスペースには、1つしかトランザクションをかけられないので、1)のトランザクションは、かかっているけど、触りようがないトランザクションになっているのです。
開けたら、閉める。これ当たり前の動作。皆さん気を付けましょう。
これでやっと、本当のバグ調査ができますよ。
2013年8月18日
Microsoft Access 2010のパッケージソリューションの作り方
最近、MS Accessでアプリケーションを作成してほしいという依頼があって作ることは簡単にできるんですが、セットアップをどう簡単にしようかと考えてました。
一番ラクなのは、ドキュメントベースでこの手順でセットアップしてくださいと書くことです。
もっとラクにするためにセットアップを作ることにしました。
MS Access2010って作ったものをパッケージしてインストーラとしてまとめてくれる機能があるんですよね。とっても便利です。
あまり、高度なことはできませんが、以下のことはやってくれるようです(自分調べ)。
「追加レジストリ キー」を設定するところがあります。
パッケージソリューションでは、Accessのランタイムを指定しインストールさせることができます。
合わせて、AccessのServicePacke1や2または、その他のインストールも同時にしたい場合、できあがったパッケージのSetup.iniを編集してやることでセットアップのプロセスに組み込むことができます。
Setup.iniは、セットアップのルート\Files\Setup\Setup.iniにあります。
では、編集方法。
Accessのランタイムをインストールするようにしておくと、「[ChainedInstall_1]」という記述を見つけることができます。これは、AcceccRuntime.exeをインストールするためのものなのでそのままにしておきます。
例えば、AccessRuntimeのサービスパック2(accessrtsp2010-kb2687444-fullfile-x86-ja-jp.exe)を同時にインストールしたい場合は、以下のように記述を追加します。
1行目は、AccessRuntimeは、「ChainedInstall_1」なので「ChainedInstall_2」にします。
2行目は、このセットアップは何かをわかりやすい名前を書きます
3行目は、実行するファイルの拡張子を書くようです。(msi形式の場合は、msi)
4行目は、実際に実行するファイルのパスを指定します。
AccessRuntime.exeが配置してあるパスにしておくのが無難だと思います。
5行目は、多分、Ignoreなのでセットアップが無効(失敗とか)だった時の戻り値だと思います。0であれば、何もなかったように次に進みます。
6行目は、不要です。実際にセットアップされるファイルへの引数だと思います。今回は不要です。
これで、Accessランタイムベースのアプリケーションのインストールがラクになると思います。
ポイントしか書いていませんので、実際にやってみてください。
一番ラクなのは、ドキュメントベースでこの手順でセットアップしてくださいと書くことです。
もっとラクにするためにセットアップを作ることにしました。
MS Access2010って作ったものをパッケージしてインストーラとしてまとめてくれる機能があるんですよね。とっても便利です。
あまり、高度なことはできませんが、以下のことはやってくれるようです(自分調べ)。
- デスクトップにショートカットを作る。
- ショートカットのアイコンが指定できる。
- スタートメニューにショートカットを作る。
- 一緒にインストールするファイルを指定できる。
- AccessのSecurityのレジストリにインストールしたフォルダを登録してくれる
→これをしないと毎回、実行していいの?って聞かれる。 - Access2010のランタイムのインストールをしてくれる。
→ランタイムを指定しておくとやってくれます。
ポイント1
[セキュリティのレジストリは、以下のように設定します。「追加レジストリ キー」を設定するところがあります。
- ルート:すべてのユーザー
他にも、 - キー:Software\Microsoft\Office\14.0\Access\Security\Trusted Locations\[任意の名前]
[任意の名前]には、例えばシステムの名前とかでも良いと思います。実際にレジストリを見るとLocation0とか書いてありますが、これらと重複しなければOKです。 - 名前:Path
- 値:[DATABASEDIR]
[DATABASEDIR]と書いておけば、ルートインストール フォルダーとインストールサブフォルダーで指定したフォルダが自動設定されます。
ポイント2
Accessランタイムのサービスパックのインストールも同時にさせる。パッケージソリューションでは、Accessのランタイムを指定しインストールさせることができます。
合わせて、AccessのServicePacke1や2または、その他のインストールも同時にしたい場合、できあがったパッケージのSetup.iniを編集してやることでセットアップのプロセスに組み込むことができます。
Setup.iniは、セットアップのルート\Files\Setup\Setup.iniにあります。
では、編集方法。
Accessのランタイムをインストールするようにしておくと、「[ChainedInstall_1]」という記述を見つけることができます。これは、AcceccRuntime.exeをインストールするためのものなのでそのままにしておきます。
例えば、AccessRuntimeのサービスパック2(accessrtsp2010-kb2687444-fullfile-x86-ja-jp.exe)を同時にインストールしたい場合は、以下のように記述を追加します。
- [ChainedInstall_2]
- TaskName=Access Runtime SP2 Setup
- TaskType=exe
- Path=\Files\accessrtsp2010-kb2687444-fullfile-x86-ja-jp.exe
- IgnoreReturnValue=0
- ;cmdline=/passive
2行目は、このセットアップは何かをわかりやすい名前を書きます
3行目は、実行するファイルの拡張子を書くようです。(msi形式の場合は、msi)
4行目は、実際に実行するファイルのパスを指定します。
AccessRuntime.exeが配置してあるパスにしておくのが無難だと思います。
5行目は、多分、Ignoreなのでセットアップが無効(失敗とか)だった時の戻り値だと思います。0であれば、何もなかったように次に進みます。
6行目は、不要です。実際にセットアップされるファイルへの引数だと思います。今回は不要です。
これで、Accessランタイムベースのアプリケーションのインストールがラクになると思います。
ポイントしか書いていませんので、実際にやってみてください。
2013年8月14日
入力画面項目チェックのロジックの提案[初心者向け]
画面入力値のチェックをするときに、1項目ずつチェックをすると思います。
その場合、入力チェック用の関数などを作ってチェックをすると思います。
その場合の構造の提案です。
例としてMS Accessで考えてみます(なんでもいいんですが)
■画面イメージ
会員ID [ ]
会員名 [ ]
If 入力チェック() Then
' エラー
Exit Sub
End If
' 登録処理をここに実装
End Sub
' True..エラーなし False..エラーあり
Private Function 入力チェック() As Boolean
Dim msg As String
Dim error_item as Control
Do
'
' 会員ID必須入力チェック
If IsNull(会員ID) Then
msg = "会員IDは、必須入力です"
Set error_item = 会員ID
Exit Do
End If
'
' 会員名必須入力チェック
If IsNull(会員名) Then
msg = "会員名は、必須入力です"
Set error_item = 会員名
Exit Do
End If
'
' 会員住所必須入力チェック
If IsNull(会員住所) Then
msg = "会員住所は、必須入力です"
Set error_item = 会員住所
Exit Do
End If
Loop Until True
if msg = "" Then
入力チェック = False
Else
入力チェック = True
MsgBox msg, vbExclamation Or vbOkOnly, "入力エラー"
error_item.SetFocus
ですが
エラーがあったら、エラーメッセージのセットとエラーのあった項目の保存をしてエラーチェックを一気に抜け、仕様のとおり、それ以降の項目チェックを行いません。
ロジックの赤字のところがポイントです。
Do Loopは、ループがしたいわけではなく、それ以降のロジックを実行したくないためにブロック構造を作り出すために使っています。
メリットとしては、以下のことがあります。
その場合、入力チェック用の関数などを作ってチェックをすると思います。
その場合の構造の提案です。
例としてMS Accessで考えてみます(なんでもいいんですが)
■仕様
- 会員ID、会員名、会員住所の必須入力チェックを行う。
- 入力チェックは、入力項目のエラーがあったら、それ以降の項目のチェックは行わない。
- エラーのあった項目にフォーカスをあてる
■画面イメージ
会員ID [ ]
会員名 [ ]
会員住所 [ ]
■ロジック
Private Sub 登録_Click()If 入力チェック() Then
' エラー
Exit Sub
End If
' 登録処理をここに実装
End Sub
' True..エラーなし False..エラーあり
Private Function 入力チェック() As Boolean
Dim msg As String
Dim error_item as Control
Do
'
' 会員ID必須入力チェック
If IsNull(会員ID) Then
msg = "会員IDは、必須入力です"
Set error_item = 会員ID
Exit Do
End If
'
' 会員名必須入力チェック
If IsNull(会員名) Then
msg = "会員名は、必須入力です"
Set error_item = 会員名
Exit Do
End If
'
' 会員住所必須入力チェック
If IsNull(会員住所) Then
msg = "会員住所は、必須入力です"
Set error_item = 会員住所
Exit Do
End If
Loop Until True
if msg = "" Then
入力チェック = False
Else
入力チェック = True
MsgBox msg, vbExclamation Or vbOkOnly, "入力エラー"
error_item.SetFocus
End If
End Function
■ポイントと解説
あまり考えないと、各項目エラーチェックをするかどうかを以前の項目でエラーがあったかのフラグを立ててチェックを行うと思います。ですが
エラーがあったら、エラーメッセージのセットとエラーのあった項目の保存をしてエラーチェックを一気に抜け、仕様のとおり、それ以降の項目チェックを行いません。
ロジックの赤字のところがポイントです。
Do Loopは、ループがしたいわけではなく、それ以降のロジックを実行したくないためにブロック構造を作り出すために使っています。
メリットとしては、以下のことがあります。
- 各入力項目は、他のエラー状態を考える必要がない
(ということは、入力チェックをする項目が増えた場合は、そのことだけを記述すればよい) - フォーカスのセッとメッセージ表示トロジックが1箇所にまとめられる
- 余計な変数を作る必要がない(弱い理由ですが)
これで、ちょっと改造しやすくて、わかりやすいプログラムができるのではないでしょうか?
登録:
投稿 (Atom)
