2017年10月23日

【Access】帳票フォームでRequeryを行ってもレコードの表示位置が変わらないようにする


帳票フォームでデータの更新などを行ってフォームのRequeryを実行するとレコードの表示が変わってしまうことがあります。そうするとシステムとしては非常に使いにくいものになってしまいます。

Accessではレコードの表示位置を覚えているわけではないのでこれは仕方ないことなのですが、ちょっとしたテクニックでこの表示位置を維持することが出来ます。

たとえばこのような帳票フォームがあるとします。



このフォームの「再表示」ボタン(buttonRequery)をクリックしてもレコード位置が変わらないようにするためには、クリックイベントプロシージャに次のように記述します。

Private Sub buttonRequery_Click()

    Dim headerHeight As Long
    Dim curTop As Long
    Dim curRecNum As Long
    Dim topRecNum As Long
    
    'IDにフォーカスを移す
    Me.ID.SetFocus
    
    'カレントレコードを取得
    curRecNum = Me.CurrentRecord
    
    'フォームヘッダー行数を取得
    headerHeight = Int(Me.Section("フォームヘッダー").Height / Me.Section("詳細").Height)
    
    '現在のセクションの上端からフォームの上端までの距離(twip)を取得
    curTop = Me.CurrentSectionTop
    
    '現在先頭に表示されているレコード番号を取得
    topRecNum = curRecNum - (Int(curTop / Me.Section("詳細").Height) - headerHeight)
    
    '再表示
    Me.Requery

    '表示位置の復元
    DoCmd.GoToRecord acActiveDataObject, , acLast
    DoCmd.GoToRecord acActiveDataObject, , acGoTo, topRecNum
    DoCmd.GoToRecord acActiveDataObject, , acGoTo, curRecNum
    
End Sub

少し解説すると、現在のカレントレコードと、画面に表示されている先頭行を記憶し、Requery後にGoToRecordを使って復元しています。

2017年10月22日

【PowerShell】Invoke-RestMethodを使って天気予報を取得してみる


最近、Web APIについてちょっと調べてたのですが、そのなかでお天気情報もWeb APIで取得できることが分かり、ためしにPowerShellで取得してみました。

まず、今回使用するWeb APIですが、livedoorの「お天気Webサービス」を使わせていただきました。
http://weather.livedoor.com/weather_hacks/webservice

こういうお天気のWeb APIって有料のところが多く、なかなか無料で使わせてもらえるところは少ないのですが、livedoorの「お天気Webサービス」は個人利用に限って無料で使うことが出来ます。


それではまず、単純にAPIを叩いてお天気情報を取得してみたいと思います。

使い方は簡単です。
Invoke-RestMethodコマンドレットのあとにAPIのURIを指定するだけです。

レスポンスはJSONで返ってきます。




PS C:\work> Invoke-RestMethod http://weather.livedoor.com/forecast/webservice/json/v1?city=140020


pinpointLocations : {@{link=http://weather.livedoor.com/area/forecast/1415000; name=相模原市}, @{link=http://weather.livedoor.com/area/forecast/1415011; name=相
                    模原市西部}, @{link=http://weather.livedoor.com/area/forecast/1415012; name=相模原市東部}, @{link=http://weather.livedoor.com/area/forecast/
                    1420600; name=小田原市}...}
link              : http://weather.livedoor.com/area/forecast/140020
forecasts         : {@{dateLabel=今日; telop=雨; date=2017-10-22; temperature=; image=}, @{dateLabel=明日; telop=雨のち晴; date=2017-10-23; temperature=; image=
                    }, @{dateLabel=明後日; telop=晴時々曇; date=2017-10-24; temperature=; image=}}
location          : @{city=小田原; area=関東; prefecture=神奈川県}
publicTime        : 2017-10-22T11:00:00+0900
copyright         : @{provider=System.Object[]; link=http://weather.livedoor.com/; title=(C) LINE Corporation; image=}
title             : 神奈川県 小田原 の天気
description       : @{text= 前線が本州の南岸に停滞しています。また、台風第21号が日本の南にあ
                    って北北東に進んでいます。

                     神奈川県は、雨となっています。

                     22日は、前線が本州南岸に停滞するため、雨で夜遅くには雷を伴って非
                    常に激しく降る所があるでしょう。

                     23日は、台風第21号の影響で、雨で朝まで雷を伴い非常に激しい雨が
                    降る所がある見込みです。午後は晴れとなる見込みです。

                     神奈川県の海上では、22日はうねりを伴いしけるでしょう。23日はう
                    ねりを伴い猛烈なしけとなる見込みです。船舶は高波に厳重に警戒してくだ
                    さい。; publicTime=2017-10-22T13:34:00+0900}
単純に実行するとこのような感じになるのですが、オブジェクト変数に格納してそれぞれの内容を個別に取得することも簡単に出来ます。

たとえば変数$tenkiに格納してみます。
PS C:\work> $tenki = Invoke-RestMethod http://weather.livedoor.com/forecast/webservice/json/v1?city=140020

ここで、タイトルを取得するには次のようにアクセスします。
PS C:\work> $tenki.title
神奈川県 小田原 の天気

また、予報を取得するには次のようにアクセスします。
PS C:\work> $tenki.forecasts


dateLabel   : 今日
telop       : 雨
date        : 2017-10-22
temperature : @{min=; max=}
image       : @{width=50; url=http://weather.livedoor.com/img/icon/15.gif; title=雨; height=31}

dateLabel   : 明日
telop       : 雨のち晴
date        : 2017-10-23
temperature : @{min=; max=}
image       : @{width=50; url=http://weather.livedoor.com/img/icon/19.gif; title=雨のち晴; height=31}

dateLabel   : 明後日
telop       : 晴時々曇
date        : 2017-10-24
temperature : @{min=; max=}
image       : @{width=50; url=http://weather.livedoor.com/img/icon/2.gif; title=晴時々曇; height=31}


さらに詳しく取得するには、次のようにアクセスします。

明日の天気
PS C:\work> $tenki.forecasts[1].telop
雨のち晴

明日の最低気温(摂氏)
PS C:\work> $tenki.forecasts[1].temperature.min.celsius
20

明日の最高気温(摂氏)
PS C:\work> $tenki.forecasts[1].temperature.max.celsius
26


非常に簡単にデータを取得できましたので、これを使っていろいろ作れそうな気がしますね。
またこんど作ったときに紹介したいと思います。





<関連記事>
天気予報を取得してWindowsフォームに表示する

2017年10月21日

【Access】マウスホイールでフォームのスクロールが出来ない


今日、たまたま気づいたのですが、Accessのフォームでマウスホイールでのスクロールが出来なくなってしまいました。

あれっ、おかしいな?

以前はたしか出来ていたはずなのに。

使用しているのは、Access2016 バージョン 1708 (ビルド 8431.2107)です。
ちなみにOSは、Windows 10 Pro バージョン 1703

ネットで検索したところ同じような症状が出ている人がいました。

その人によるとアップデートしたところ治ったとのこと。

さっそくアップデートしてみました。

⇒バージョン 1709 (ビルド 8528.2139)

2017年10月20日

【Access】フォームOpenをキャンセルする


フォームを開くときに何かの理由でキャンセルしたい場合があったりします。
そういった場合、Openイベントプロシージャの引数CancelをTrueにします。

次の例では、フォームOpen時にInputBoxでパスワードを入力させ、パスワードが一致していた場合だけフォームを開くようにしています。
'パスワード
Private Const PWD As String = "tako"

Private Sub Form_Open(Cancel As Integer)

    Dim pass As String
    
    pass = InputBox("パスワードを入力してください。")
    
    If pass <> PWD Then
    
        MsgBox "パスワードが間違っています。" & vbCrLf & "フォームを開くことが出来ませんでした。", vbExclamation, "警告"
        
        'キャンセル
        Cancel = True
    
    End If
    
End Sub

2017年10月19日

【Access】実行中のフォームのコントロールを再描画する


Repaintメソッドを使って実行中のフォームのコントロールを再描画することが出来ます。

たとえば、フォームにラベル(labelHello)が貼り付けてあり、このラベルのフォントサイズをボタン(buttonBig、buttonSmall)を押すことで変更させてみたいと思います。



各ボタンのイベントプロシージャに次のように記述します。
Private Sub buttonBig_Click()

    Me.labelHello.FontSize = Me.labelHello.FontSize + 1
    
    '再描画
    Me.Repaint
    
End Sub

Private Sub buttonSmall_Click()

    Me.labelHello.FontSize = Me.labelHello.FontSize - 1
    
    '再描画
    Me.Repaint

End Sub

2017年10月18日

【Access】VBAでフォームを作成する


VBAでフォームを作成するにはCreateFormメソッドを使います。

たとえば、このようなaccdbファイルがあったとします。


ここで、次のプロシージャを実行してみます。
Public Sub MakeForm()

    CreateForm
    
    DoCmd.Restore
    
End Sub

2017年10月17日

【Access】最大化/最小化されたフォームを元に戻す


最大化/最小化されたフォームを元に戻すにはDoCmd.Restoreを使います。

たとえば、このようなフォームにボタンが2つ貼り付けてあるとします。


「最大化」ボタンでフォームを最大化、「元に戻す」ボタンでフォームを元に戻すようにするには次のように記述します。
Private Sub buttonMaximize_Click()

    '最大化
    DoCmd.Maximize
    
End Sub

Private Sub buttonRestore_Click()

    '元に戻す
    DoCmd.Restore

End Sub