ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

画像ボタンを作成してみる。

カスタムボタンを定義

とりあえず、カスタムボタンを定義し、基本的にスタイルのみ設定していみる。

<Button x:Class="MyButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:App1"
             mc:Ignorable="d" >
    <Button.Style>
        <Style TargetType="Button" >
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="FontSize" Value="25" />
            <Setter Property="FontWeight" Value="Bold" />
        </Style>
    </Button.Style>

ControlTemplateでボタンの内部構成とTriggerで表示・非表示を切り替える。

状態ごとに、表示を切り替えているだけだが、上手く動いた

    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Grid>
                <Image Name="Normal" Source="/App1;component/Images/btn_normal.png"/>
                <Image Name="MouseOver" Source="/App1;component/Images/btn_mouseover.png" Visibility="Hidden"/>
                <Image Name="Pressed" Source="/App1;component/Images/btn_pressed.png" Visibility="Hidden"/>
                <Image Name="Disabled" Source="/App1;component/Images/btn_gray.png" Visibility="Hidden"/>
                <TextBlock Name="NormalText" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Text="{TemplateBinding Content}"/>
                <TextBlock Name="PressedText" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Foreground="White" Text="{TemplateBinding Content}"  Visibility="Hidden"/>
                <TextBlock Name="DisabledText" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Foreground="Gray" Text="{TemplateBinding Content}"  Visibility="Hidden"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsPressed" Value="True">
                    <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="NormalText" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>
                    <Setter TargetName="PressedText" Property="Visibility" Value="Visible"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="MouseOver" Property="Visibility" Value="Visible"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="NormalText" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="Disabled" Property="Visibility" Value="Visible"/>
                    <Setter TargetName="DisabledText" Property="Visibility" Value="Visible"/>
                </Trigger>
            </ControlTemplate.Triggers>
           
        </ControlTemplate>
    </Button.Template>

batファイル用コマンドメモ

変数使用

SET HOGE=abc
ECHO %HOGE%

日付取得

日付はシステムの日付フォーマットで表示されるため、ファイル名などに使うには部分を取得し、合体させる必要がある。

ECHO %date%
YYYY/MM/DD
ECHO %time%
HH:MM:SS.SS
ECHO  %date:~0,4%%date:~5,2%%date:~8,2%
YYYYMMDD

for分

for %%アルファベット1文字 in (対象) do コマンド

for %%i in (*.log) do (
  echo %%i
)

遅延環境変数

batファイル内の変数への値設定と読み込むタイミングにより、変数の値が正しくならないため、遅延環境変数を設定する。 遅延環境変数は「!」+「変数名」+「!」でループ内で実行時に取得するようになる。

setlocal enabledelayedexpansion
for %%f in (01,02,03,04,05) do (
    SET FNAME=%%f.log
    echo create file : !FNAME!
    echo !FNAME! > !FNAME!
)
endlocal

DataGrid 操作についてメモ

DataGridTextColumn

セルのスタイルを編集する場合 DataGridTextColumn.ElementStyleを利用し、スタイルを指定する

<DataGrid>
  <DataGrid.Columns>
    <DataGridTextColumn Header="ヘッダー名" Binding="{Binding MyDate,StringFormat=yyyy/MM/dd}" Width="100">
      <DataGridTextColumn.ElementStyle>
        <Style TargetType="TextBlock">
          <Setter Property="TextAlignment"  Value="Center" />
        </Style>
      </DataGridTextColumn.ElementStyle>
    </DataGridTextColumn>
  </DataGrid.Columns>
</DataGrid>

セルをカスタマイズ

DataGridTemplateColumnを利用し、DataTemplateを配置する

<DataGrid>
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="ヘッダー名" Width="100">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <Button Command="{Binding ButtonActionCommand}" >押す/Button>
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

編集可能セルを設定する

DataGridTextColumnでもIsReadOnlyがFalseの場合、ダブルクリックで編集可能だが、カスタムしたい場合、CellEditingTemplateを使用する。 ただし、表示時のTempleteも指定しないと表示されないため、CellTemplateも設定する必要がある。 ※DataGridTemplateColumnではCellEditingTemplateの中にバインドしたものだけが正しくSet処理が実行される。

<DataGrid>
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="ヘッダー名" Width="100">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding Text1}" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
      <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
          <TextBox Text="{Binding Text1}"/>
        </DataTemplate>
      </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

セルダブルクリックイベントをCommandで受け取る方法

DataGrid.InputBindingsにMouseBindingを設定し、イベントアクションをCommandにつなぐ

<DataGrid>
  <DataGrid.InputBindings>
    <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding GridMouseDoubleClickCommand}"/>
  </DataGrid.InputBindings>
</DataGrid>

ヘッダー表示をカスタマイズする。

HeaderTemplateを利用し、ヘッダーを2行表示する。

<DataGrid>
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="ヘッダー名" Width="100">
      <DataGridTemplateColumn.HeaderTemplate>
        <DataTemplate>
          <StackPanel>
            <TextBlock Text="ヘッダー1行" />
            <Separator/>
            <TextBlock Text="ヘッダー2行" />
          </StackPanel>
        </DataTemplate>
      </DataGridTemplateColumn.HeaderTemplate>
  </DataGrid.Columns>
</DataGrid>

CSVファイルからのBULK INSERT

CSVファイルからSQL ServerのTableへ高速でデータを投入する

私用場面は色々あるが、とりあえず、スキーマ間でデータを移動する場合を想定します。

復元もとDBからデータを抽出するためのSQLをファイルに記載します。

output.sql

SET NOCOUNT ON
;
SELECT 
       *
FROM [dbo].[MyTable];

コマンドラインからSqlファイルのSQLを実行し、CSVファイルに吐き出します。

SQLCMD -S localhost -U sa -P {password} -d {dbname} -i output.sql -s, -W -h -1 -o output.csv

出力されたファイルを復元先DBからアクセス可能なパスにおいてBulk Insertを実行します。

bulk insert dbo,MyTable
from '\\c\work\output.csv'
WITH 
( 
FIELDTERMINATOR = ',', 
ROWTERMINATOR = '\n' 
);

ADO.NET Entity Data Model(edmx)で生成した接続文字列をコードで生成する。

ADO.NET Entity Data Model(edmx)で生成した場合

app.config内部にmetadataを含むConnectionStringが生成される。せっかく自動生成したEntity Data Modelを再利用しながら、ConnectionStringをConfigファイルから隠したいため、コードベースで生成する必要があった

DataContext修正

edmxの内部のDbContextクラスにDbConnectionをもらうコンストラクタを追加する。 f:id:haronoid:20180928130636p:plain

Partial Public Class DbEntities
    Inherits DbContext

    Public Sub New()
        MyBase.New("name=DbEntities")
    End Sub

     ' 追加
    Public Sub New(conn As DbConnection)
        MyBase.New(conn, True)
    End Sub

End Class

追記:DALの更新時、追加したコンストラクタが消えてしまう事がわかったため、別のAppDbContextクラスで対応

Public Class AppDbContext
    Inherits DbContext

    Public Sub New(conn As Common.DbConnection)
        MyBase.New(conn, True)
    End Sub

    '''
    ''' 以下の部分はDbEntitiesの自動生成プロパティをコピー・ペーストしてあげる。
    '''
End Class

DBコネクション処理修正

' Initialize the connection string builder
Dim sqlBuilder As New SqlConnectionStringBuilder() With {
    .DataSource = "localhost",
    .InitialCatalog = "testdb",
    .UserID = "sa",
    .Password = "mypassword",
    .IntegratedSecurity = True
    }

' Initialize the EntityConnectionStringBuilder. 
Dim entityBuilder As New EntityConnectionStringBuilder() With {
    .Provider = "System.Data.SqlClient",
    .ProviderConnectionString = sqlBuilder.ToString(),
    .Metadata = "res://*/DbModel.csdl|res://*/DbModel.ssdl|res://*/DbModel.msl"
    }

_dbContext = New DAL.AppDbContext(New EntityConnection(entityBuilder.ToString()))

参考

EntityConnection の接続文字列を作成する方法 | Microsoft Docs

Windows Server 2003, ASP.NET, IIS6.0

Windows Server 2003環境のIIS設定

仕事上、旧システムを動かしている現場があり、仮想環境に現状での移行をしてみたので、メモとしてやった事を記録する。

Windows Server 2003 R2のインストール

OSインストールCDは必要! 無料での入手は出来ない(公開されていない) サポートもとっくに切れている

.NET 2.0のインストール

.NET 2.0はMicrostのアーカイブから入手可能 https://www.microsoft.com/ja-jp/download/details.aspx?id=1639

IIS 6.0のインストール

当然ながら、Windows 2003なので、IISも6.0 インストールは以下の手順で行う

※途中からOSのCDを要求される。

ASP.NET AJAX 1.0のインストール

ASP.NET上でAjaxを使っている場合、AJAX Extentionsが必要となる。以下のURLから入手可能

https://www.microsoft.com/en-us/download/confirmation.aspx?id=883

ASP.NET 状態サービス

ログイン情報管理をASP.NET 状態サービスを利用する場合、Windowsのサービスから「ASP.NET 状態サービス」を起動する必要がある。

Google Home, IFTTT, Google Sheet, Slack連携

概要

Google Homeから最終的にSlackのチャンネルにポストするまでをためしてみた。 連携はIFTTTからGoogle Sheetへ書き込み、Google SheetからSlackへポストする流れとなる。

IFTTT連携(Google Home → Google Sheet)

My Applet タブから「New Applet」を洗濯 f:id:haronoid:20180721193840p:plain

Triggerを設定するため「+this」を選択 f:id:haronoid:20180721193928p:plain

Google Assistantを検索し、以下の画面から「Say a phrase with a text ingredient」を選択 f:id:haronoid:20180721194122p:plain

Google Homeがトリガとするキーワードと読み取る文字列($)を指定、今回は「受付」をトリガーにその後の文字列を訪問者名として認識する設定 f:id:haronoid:20180721194316p:plain

Triggerが終わるとAction指定のため「+that」を選択 f:id:haronoid:20180721194352p:plain

Action処理としてgoogle sheetを選択 f:id:haronoid:20180721194428p:plain

訪問者リストファイルのB2セルにトリガーで読み取った「$」が設定される様に設定 f:id:haronoid:20180721194527p:plain

Slack連携(Google Sheet → Slack)

これまでの設定が問題なければ、「OK Google 受付 ○○○」で指定したGoogle Sheetに内容が記録されるはず。

f:id:haronoid:20180721201556p:plain 訪問リストから、スクリプトエディターを選択し、以下のスクリプトを記載する。 (ソースは最後の参考URL本家のソースのそのままである。ただし、今後変更予定)

function showStatus() {
  var mySheet = SpreadsheetApp.getActiveSheet();      // シートを取得
  var currentRow = mySheet.getActiveCell().getRow();  // 更新行を取得
  var myCell = mySheet.getActiveCell();               // アクティブなセルの取得

  if(myCell.getColumn() == 2) { //数字の部分には列番号(この場合B列)
    // 更新日時をA1に記録する
    var updateRange = mySheet.getRange('A' + currentRow);
    updateRange.setValue(Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/M/d H:m:s'));

    var text = myCell.getValue() + '様が来訪されました';
    slackPost();    

    // 更新行を記述するため1行追加
    mySheet.insertRowBefore(2);

  }

  function slackPost() {
  var url        = 'https://slack.com/api/chat.postMessage';
  var token      = 'xoxp-xxxxxxxxxxxxxx';
  var channel    = '#チャンネル名';
  var username   = '来訪通知';
  var parse      = 'full';
  var icon_emoji = '';
  var method     = 'post'; 
  var payload = {
    'token'      : token,
    'channel'    : channel,
    'text'       : text,
    'username'   : username,
    'parse'      : parse,
    'icon_emoji' : icon_emoji
  };
  var params = {
    'method' : method,
    'payload' : payload
  };
  var response = UrlFetchApp.fetch(url, params);
  }
}

※ Slack Tokenは以下のリンクから生成することが可能 https://api.slack.com/custom-integrations/legacy-tokens

最後に、Google Sheetのトリガーを設定する。 f:id:haronoid:20180721202017p:plain 新しいトリガーとして、変更が発生したタイミングでshowStatusが実行される。 f:id:haronoid:20180721202038p:plain

ここまで、問題がなければ、指定したSlackのチャンネルにポストされるはず。

参考

qiita.com