So-net無料ブログ作成

Edge仕様のWebBrowserコントロール(WebView) [VB.NET]

WebBrowserコントロールを使うとIE仕様になってしまい、サイトによってはJavaScriptが動かなかったりします。
そこで、WebBrowserコントロール(IE)ではなく、WebViewコントロール(Edge)を使用します。

実行環境が決まってるようで、このバージョン以降が必要のようです。
・Windows 10 1803
・Visual Studio 2017
・.NET Framework 4.6.2


Visual Studio 2017 を起動し、NuGet から次のパッケージをインストールします。
この文字列で検索すると見つかります。
「Microsoft.Toolkit.Forms.UI.Controls.WebView」

ツールボックスの「アイテムの選択」から「.NET Framework コンポーネント」タブを開き
次のパスのdllを参照から開きます。
C:\Users\<ユーザー名>\.nuget\packages\microsoft.toolkit.forms.ui.controls.webview\5.1.1\lib\net462\Microsoft.Toolkit.Forms.UI.Controls.WebView.dll


あとは、ツールボックスからWebViewコントロールをフォームに張り付けて完成。

フォームを開くとユーザーIDとパスワードが入力されてログインしたいときのサンプルプログラム
Imports Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT

Public Class frmMain
    Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        WebView1.Navigate("https://www.example.com/login.html")
    End Sub

    Private Sub WebView1_NavigationCompleted(sender As Object, e As WebViewControlNavigationCompletedEventArgs) Handles WebView1.NavigationCompleted

        If WebView1.DocumentTitle = "ログイン画面" Then
            Dim script As New System.Text.StringBuilder

            'ユーザーID uuuuu を入力
            script.AppendLine(String.Format("document.getElementsByName('UserId').item(0).value = '{0}';", "uuuuu"))
            'パスワード ppppp を入力
            script.AppendLine(String.Format("document.getElementsByName('Password').item(0).value = '{0}';", "ppppp"))

            WebView1.InvokeScript("eval", script.ToString())

            'ログインボタンを探してクリック
            script.Clear()
            script.AppendLine("for (i in document.getElementsByTagName('input')) {")
            script.AppendLine("    if (document.getElementsByTagName('input').item(i).value === 'ログイン') {")
            script.AppendLine("        document.getElementsByTagName('input').item(i).click();")
            script.AppendLine("    }")
            script.AppendLine("}")

            WebView1.InvokeScript("eval", script.ToString())
        End If

    End Sub
End Class


WebBrowserコントロールにあったDocumentプロパティが見当たらなくて
inputタグにどうやって値を入れるの?と、だいぶ困った。
WebViewコントロールはJavaScriptでhtmlを操作するようだ。

参考URL:WPFやWindowsフォームでEdgeのWebViewを使うには?[Windows 10 1803以降]:.NET TIPS - @IT
参考URL:【C#】WebBrowserコントロールをEdgeに対応させる | 思い立ったが吉日

さらにメモ
Chromium仕様のブラウザコントロール(CefSharp)もあるみたい。
参考URL:WinFormsでChromiumブラウザコンポーネント(CefSharp)を使ってみる
参考URL:VB.net(WinForms)でのCefsharpの基本的な扱い方について
nice!(0)  コメント(0) 

DataGridViewのセルで右寄せにしたときの余白を設定する [VB.NET]

DataGridViewのセルに数値データを右寄せで表示したとき、
右端に行き過ぎて何となくいやだなと思ったので、セルの余白調整方法を調べた。

dgv.Columns("ITEM_VALUE").DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
dgv.Columns("ITEM_VALUE").DefaultCellStyle.Padding = New Padding(0, 0, 20, 0)


右の余白を20に設定したら次のようになった。
20190513_001.png
nice!(0)  コメント(0) 

画面作成中にユーザーコントロールのLoadイベントを処理させない [VB.NET]

ユーザーコントロールを使用したForm画面の作成中に次のエラーが出てForm画面が開かなくなった。
"ユーザー '' はログインできませんでした。"

ユーザーコントロールのLoadイベントにApp.configからDBへの接続情報を取得して
DBからデータを取得、表示をするプログラムを追加してからエラーが出ていた。

Form画面を開くときに、配置したユーザーコントロールのLoadイベントが実行され
App.configから接続情報を取得できていないのが原因で、DBへの接続ができずエラーとなっていた。

画面作成中は、Loadイベントが実行されないようにしようと思って調べた時のメモ。
Private Sub UserCtrl_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    '開発中は処理をしない
    If Me.DesignMode Then Return

    'DBへの接続と取得・表示

End Private

参考URL:.NET:Tips > デザイン:デザイン時に処理を実行させない

ユーザーコントロールが入れ子になっているとき、子のユーザーコントロールの
DesignModeはFalseを返すようです。
その情報を調べた時のメモ。
参考URL:デザインモード(this.DesignMode)を正しく得ることができない場合があります
参考URL:入れ子させた UserControl の DesignMode が false になるのを回避したい
nice!(1)  コメント(0) 

DataGridViewのセル編集が3回クリックで編集できるようになる [VB.NET]

DataGridViewでセルを直接編集するために編集を有効にしたけど
セルを3回クリックしないと、編集モードにならなかった。

1回目のクリックで、セルが選択され
次のダブルクリックで編集モードになってる?

ダブルクリックで編集モードとなるようにしたかったのでプログラムのメモ。
'EditModeを次の設定に変更する
'DataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically
Private Sub DataGridView1_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick
    Dim dgv As DataGridView = DirectCast(sender, DataGridView)

    If {"Column1", "Column2", "Column3"}.Contains(dgv.Columns(e.ColumnIndex).Name) AndAlso e.RowIndex >= 0 Then
        dgv.BeginEdit(True)
    End If
End Sub

nice!(0)  コメント(0) 

PC(Windows 10)の時刻を設定するために盾マークのexeを作成 [VB.NET]

Windows 10になってからではないけど、システム時刻をプログラムから合わせるには
ユーザーアカウント制御を何とかするか、管理者権限で実行するかしないと出来なくなった。

タスクスケジューラに登録して管理者で実行する方法もあるみたい。

ユーザーアカウント制御の実行を聞かれるのはしょうがないと諦めて
右クリックして"管理者として実行"をしなくても良いように盾マークのexeを作成することにした。
参考URL:再試行でDebugできない~VS2015

次のプログラムを「NTPサーバの現在日時をシステム時計に設定するサンプル(VB.NET)」を転記しています。
タイムサーバーは、time.windows.com です。
Public Class Form1

    ' システム時計の日時設定APIの引数
    <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>
    Public Structure SystemTime
        Public wYear As Short
        Public wMonth As Short
        Public wDayOfWeek As Short
        Public wDay As Short
        Public wHour As Short
        Public wMinute As Short
        Public wSecond As Short
        Public wMiliseconds As Short
    End Structure

    ' システム時計の日時設定APIの定義
    <System.Runtime.InteropServices.DllImport("kernel32.dll")>
    Public Shared Function SetLocalTime(ByRef sysTime As SystemTime) As Boolean
    End Function

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        ' NTPサーバへの接続用UDP生成
        Dim objSck As System.Net.Sockets.UdpClient
        Dim ipAny As System.Net.IPEndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)
        objSck = New System.Net.Sockets.UdpClient(ipAny)

        ' NTPサーバへのリクエスト送信
        Dim sdat As Byte() = New Byte(47) {}
        sdat(0) = &HB
        objSck.Send(sdat, sdat.GetLength(0), "time.windows.com", 123)

        ' NTPサーバから日時データ受信
        Dim rdat As Byte() = objSck.Receive(ipAny)

        ' 1900年1月1日からの経過時間(日時分秒)
        Dim lngAllS As Long ' 1900年1月1日からの経過秒数
        Dim lngD As Long    ' 日
        Dim lngH As Long    ' 時
        Dim lngM As Long    ' 分
        Dim lngS As Long    ' 秒

        ' 1900年1月1日からの経過秒数計算
        lngAllS = CLng(
                  rdat(40) * Math.Pow(2, (8 * 3)) +
                  rdat(41) * Math.Pow(2, (8 * 2)) +
                  rdat(42) * Math.Pow(2, (8 * 1)) +
                  rdat(43))

        ' 1900年1月1日からの経過(日時分秒)計算
        lngD = lngAllS \ (24 * 60 * 60)   ' 日
        lngS = lngAllS Mod (24 * 60 * 60) ' 残りの秒数
        lngH = lngS \ (60 * 60)           ' 時
        lngS = lngS Mod (60 * 60)         ' 残りの秒数
        lngM = lngS \ 60                  ' 分
        lngS = lngS Mod 60                ' 秒

        ' 現在の日時(DateTime)計算
        Dim dtTime As DateTime = "1900/01/01"
        dtTime = dtTime.AddDays(lngD)
        dtTime = dtTime.AddHours(lngH)
        dtTime = dtTime.AddMinutes(lngM)
        dtTime = dtTime.AddSeconds(lngS)

        ' グリニッジ標準時から日本時間への変更
        dtTime = dtTime.AddHours(9)

        ' 現在の日時表示
        System.Diagnostics.Trace.WriteLine(dtTime)

        ' システム時計の日時設定
        SetSysTime(dtTime)

    End Sub

    ' システム時計の日時設定
    Private Sub SetSysTime(ByVal dtm As DateTime)
        Dim sTime As New SystemTime
        sTime.wYear = dtm.Year
        sTime.wMonth = dtm.Month
        sTime.wDay = dtm.Day
        sTime.wHour = dtm.Hour
        sTime.wMinute = dtm.Minute
        sTime.wSecond = dtm.Second
        sTime.wMiliseconds = dtm.Millisecond
        SetLocalTime(sTime)
    End Sub

End Class


ソリューション エクスプローラーからプロジェクトを右クリックして[追加]→[新しい項目]をクリックする。
"アプリケーション マニフェスト ファイル"を選択して追加する。
app.manifestにある次行を変更する。(コメントされているのをコピーして貼り付けると良い)
変更前: 
<requestedExecutionLevel level="asInvoker" uiAccess="false" />

変更後: 
<requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />

20181226_1059.png

ソリューションをリビルドしたらexeに盾マークが付いている。
このexeを実行すると、ユーザーアカウント制御が聞かれるので"はい"を押す。
nice!(1)  コメント(0) 

DataGridViewのセル結合(行のセルを固定) [VB.NET]

以前に書いた記事で「DataGridViewでセルを結合」をしたときだと、行を固定した場合、上手く描画できません。

その対応したプログラムを書いたのでメモ。

・表を見せるのみです。
・行列の追加、編集、削除や、セル幅の変更は考慮していません。
・行列のヘッダーは無効にしています。
・DataGridViewコントロールの名前は、「DataGridView1」です。
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    Init()

End Sub

Private Sub Init()

    'ちらつき防止
    Dim type As System.Type = GetType(DataGridView)
    Dim propertyInfo As System.Reflection.PropertyInfo = type.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.NonPublic)
    propertyInfo.SetValue(DataGridView1, True, Nothing)

    DataGridView1.AllowUserToAddRows = False
    DataGridView1.ReadOnly = True
    DataGridView1.AllowUserToDeleteRows = False
    DataGridView1.ColumnHeadersVisible = False
    DataGridView1.RowHeadersVisible = False

    Dim i As Integer
    Dim j As Integer
    Dim colAdd As DataGridViewColumn
    For i = 1 To 3
        colAdd = New DataGridViewColumn
        colAdd.Name = String.Format("Column{0}", i)
        colAdd.Width = 60
        colAdd.CellTemplate = New DataGridViewTextBoxCell
        DataGridView1.Columns.Add(colAdd)
    Next

    '結合したいセルには同じテキストを入れておく
    Dim cellText(,) As String = {
        {"店舗", "店舗", "売上"},
        {"店舗名", "担当エリア", "売上"},
        {"北支店01", "駅北", "10000"},
        {"北支店02", "駅南", "9000"},
        {"西支店03", "商店街", "12000"},
        {"東支店04", "住宅区", "8000"},
        {"南支店05", "商業区", "11000"},
        {"北支店06", "駅北", "10000"},
        {"北支店07", "駅南", "9000"},
        {"西支店08", "商店街", "12000"},
        {"東支店09", "住宅区", "8000"},
        {"南支店10", "商業区", "11000"},
        {"北支店11", "駅北", "10000"},
        {"北支店12", "駅南", "9000"},
        {"西支店13", "商店街", "12000"},
        {"東支店14", "住宅区", "8000"},
        {"南支店15", "商業区", "11000"},
        {"北支店16", "駅北", "10000"},
        {"北支店17", "駅南", "9000"},
        {"西支店18", "商店街", "12000"},
        {"東支店19", "住宅区", "8000"},
        {"南支店20", "商業区", "11000"}
    }
    Dim rowAdd As DataGridViewRow
    For i = 0 To cellText.GetLength(0) - 1
        rowAdd = New DataGridViewRow
        rowAdd.CreateCells(DataGridView1)
        For j = 0 To rowAdd.Cells.Count - 1
            rowAdd.Cells(j).Value = cellText(i, j)
        Next
        DataGridView1.Rows.Add(rowAdd)
    Next

    'ヘッダー行を固定とする
    DataGridView1.Rows(1).Frozen = True

End Sub

Private Sub DataGridView1_CellPainting(sender As Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting

    '結合したいセルをここに書く
    MergeCell(e, New Point(0, 0), New Point(1, 0))
    MergeCell(e, New Point(2, 0), New Point(2, 1))
    MergeCell(e, New Point(0, 1), New Point(0, 1))
    MergeCell(e, New Point(1, 1), New Point(1, 1))

End Sub

'Cell1には、セルの開始位置(X, Y)
'Cell2には、セルの終了位置(X, Y)
Private Sub MergeCell(ByRef e As System.Windows.Forms.DataGridViewCellPaintingEventArgs, Cell1 As Point, Cell2 As Point)

    If (e.RowIndex >= Cell1.Y AndAlso e.RowIndex <= Cell2.Y) AndAlso (e.ColumnIndex >= Cell1.X AndAlso e.ColumnIndex <= Cell2.X) Then

        Dim rect As New Rectangle With {.X = 0, .Y = 0, .Width = 0, .Height = 0}
        Dim i As Integer
        Dim firstRowIndex As Integer

        '固定セルであれば、先頭から描画されているとする
        If DataGridView1.Rows(e.RowIndex).Frozen = True Then
            firstRowIndex = 0
        Else
            firstRowIndex = DataGridView1.FirstDisplayedScrollingRowIndex
        End If

        '開始セルの位置
        '結合セルが画面外にあるときの位置を考慮
        For i = Cell1.Y + 1 To firstRowIndex
            rect.Y -= DataGridView1(Cell1.X, i - 1).Size.Height
        Next
        For i = firstRowIndex + 1 To Cell1.Y
            rect.Y += DataGridView1(Cell1.X, i - 1).Size.Height
        Next
        '結合セルが画面外にあるときの位置を考慮
        For i = Cell1.X + 1 To DataGridView1.FirstDisplayedScrollingColumnIndex
            rect.X -= DataGridView1(i - 1, Cell1.Y).Size.Width
        Next
        For i = DataGridView1.FirstDisplayedScrollingColumnIndex + 1 To Cell1.X
            rect.X += DataGridView1(i - 1, Cell1.Y).Size.Width
        Next

        '終了セルの幅
        For i = Cell1.Y To Cell2.Y
            rect.Height += DataGridView1(Cell2.X, i).Size.Height
        Next
        For i = Cell1.X To Cell2.X
            rect.Width += DataGridView1(i, Cell2.Y).Size.Width
        Next

        'セル位置の補正
        rect.X += 1
        rect.Y += 1

        'グラデーションをかけてヘッダーぽく見せる
        Dim gb As New System.Drawing.Drawing2D.LinearGradientBrush(rect, SystemColors.ControlLightLight, SystemColors.Control, System.Drawing.Drawing2D.LinearGradientMode.Vertical)
        gb.GammaCorrection = True

        '通常の塗りつぶし
        'e.Graphics.FillRectangle(New SolidBrush(SystemColors.Control), rect)
        e.Graphics.FillRectangle(gb, rect)
        e.Graphics.DrawRectangle(New Pen(DataGridView1.GridColor), rect)

        gb.Dispose()

        '描画するセル位置の文字をヘッダーテキストとして表示
        Dim headerText As String = DataGridView1(e.ColumnIndex, e.RowIndex).Value
        TextRenderer.DrawText(e.Graphics, headerText, e.CellStyle.Font, rect, e.CellStyle.ForeColor, TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter)

        e.Handled = True

    End If

End Sub


20181220_00.png
nice!(0)  コメント(1) 

WebBrowserコントロールでポップアップ表示されるユーザーとパスワードの入力 [VB.NET]

WebBrowserコントロールで機器接続用の専用ブラウザを作っていて
ユーザーとパスワードの入力をポップアップで聞いてくるのがあった。
BASIC認証.png

色々調べるとBASIC認証すれば接続できたので、そのときのメモ。

接続するURLを次のようにして接続した。
httpとIPアドレスの間に、<ユーザー名>:<パスワード>@ を追加した。
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim userName As String = "mainte"
    Dim password As String = "99999"
    Dim urlString As String = "http://" & userName & ":" & password & "@192.168.0.254/"
    ExWebBrowser1.Navigate(urlString)
End Sub

nice!(0)  コメント(0) 

WebBrowserコントロールでもwindow.close()で閉じたい [VB.NET]

最近の機器にはブラウザで設定が出来るものが多いです。
そこで、WebBrowserコントロールを使って特定のページを表示する簡易ブラウザを作成しました。
作成にあたり、保守モードが最初から選択されてたり、特定の文字が入力済みであったりと
HtmlDocumentを解析しながら組み込みました。

そういった設定画面は、閉じるボタンを押すとブラウザが終了するのが多いのですが
作成した簡易ブラウザでは閉じるボタンを押すとフリーズしたようになります。

window.closeのイベントを取得するように変更しました。
参考にしたのは次のURLです。
WebBrowserコントロールにWindowClosingイベントもどきを拡張する

FormにExWebBrowserを配置します。
Form1.vb
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim urlString As String = "http://192.168.10.1/"
    ExWebBrowser1.Navigate(urlString)
End Sub

Private Sub ExWebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles ExWebBrowser1.DocumentCompleted
    Dim name As String = "login.html"
    If e.Url.OriginalString.IndexOf(name) > 0 Then
            'フレームで構成されているため、表示されたフレームから目的のページで処理を行う
            Dim frames As HtmlWindowCollection = WebBrowser1.Document.Window.Frames
            For Each frame As HtmlWindow In frames
                '"login.html"で処理をする
                If frame.Document.Url.OriginalString.IndexOf(name) > 0 Then
                    Dim doc As HtmlDocument = frame.Document
                    Dim all As HtmlElementCollection = doc.All
                    
                    'ユーザーを入力
                    Dim user As HtmlElementCollection = all.GetElementsByName("user")
                    user(0).InnerText = "99"
                    
                    'パスワードを入力
                    Dim pass As HtmlElementCollection = all.GetElementsByName("pass")
                    pass(0).InnerText = "999999"
                End If
            Next
    End If
End Sub

Private Sub ExWebBrowser1_WindowClosing(sender As Object, e As EventArgs) Handles ExWebBrowser1.WindowClosing
    Me.Close()
End Sub

ExWebBrowser.vb
Imports System.Runtime.InteropServices

Public Class ExWebBrowser
    Inherits WebBrowser

    Sub New()
        MyBase.New()
    End Sub

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    Private Shared Function GetWindow(ByVal hWnd As IntPtr, ByVal uCmd As UInt32) As IntPtr
    End Function

    Private Enum GetWindowType As UInt32
        GW_HWNDFIRST = 0
        GW_HWNDLAST = 1
        GW_HWNDNEXT = 2
        GW_HWNDPREV = 3
        GW_OWNER = 4
        GW_CHILD = 5
        GW_ENABLEDPOPUP = 6
    End Enum

    Public Event WindowClosing As EventHandler

    Protected Overridable Sub OnWindowClosing(ByVal e As EventArgs)
        RaiseEvent WindowClosing(Me, e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_PARENTNOTIFY As Int32 = &H210
        Const WM_DESTROY As Int32 = &H2

        If m.Msg = WM_PARENTNOTIFY Then
            If m.WParam.ToInt32() = WM_DESTROY Then
                If m.LParam = GetWindow(Me.Handle, GetWindowType.GW_CHILD) Then
                    Dim e As EventArgs = New EventArgs()
                    OnWindowClosing(e)
                    Return
                End If
            End If
        End If
        MyBase.WndProc(m)
    End Sub

End Class

nice!(0)  コメント(0) 

Excelの操作用ライブラリ(NPOI)の使い方 [VB.NET]

Excelの操作にCOMを使っていたけど、プロセスが解放されたりされなかったりと
どうにもこうにもなので、Excelの操作用ライブラリ「NPOI」を使ってみることにした。

参考URL
【C#】NPOIを使ってExcelファイルを作成・編集する

Visual Studio 2013を使いました。
1. メニューの[Tool]→[NuGetパッケージマネージャー]→[ソリューションのNuGetパッケージの管理]と押す。
2. 右上にあるオンラインの検索から「NPOI」と入力し検索をする。
3. 見つかれば「インストール」ボタンを押してインストールをする。

Imports NPOI.SS.UserModel

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    'Excelを開く
    Dim book As IWorkbook = WorkbookFactory.Create("C:\Test.xls")
    '最初のシートを選択
    Dim sheet As ISheet = book.GetSheetAt(0)
    'セルに値の書き込み
    WriteCell(sheet, 2, 1, 12345)
    WriteCell(sheet, 2, 2, "あいうえお")
    WriteCell(sheet, 2, 3, DateTime.Now)
    'セルの値を読み込み
    Dim value As String = ""
    GetCell(sheet, 2, 1, value)
    GetCell(sheet, 2, 2, value)
    GetCell(sheet, 2, 3, value)
    'Excelの保存
    SavedBook(book, path)
    'Excelを閉じる
    book.Close()

End Sub

Private Sub SavedBook(ByRef book As IWorkbook, ByVal filePath As String)

    Using fs As New System.IO.FileStream(filePath, IO.FileMode.Create)
        book.Write(fs)
    End Using

End Sub

Private Sub GetCell(ByRef sheet As ISheet, ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByRef value As String)

    Dim row As IRow = If(sheet.GetRow(rowIndex - 1), sheet.CreateRow(rowIndex - 1))
    Dim cell As ICell = If(row.GetCell(columnIndex - 1), row.CreateCell(columnIndex - 1))
    'Cellのタイプを判断して対応するメソッドを呼ばないと値が取れないので
    'とりあえず全部文字列で取得する。
    'ただし、日付はExcelで見た時と取得した値が違っている
    'ユーザー定義の書式を見て、自分で変換する?
    'cell.DateCellValue の値を取得して自分で変換した方が良いかも
    'Excelに指定されているユーザー定義は cell.CellStyle.GetDataFormatString() で取得できる
    Dim formatter As DataFormatter = New DataFormatter()
    value = formatter.FormatCellValue(cell)

End Sub

Private Sub WriteCell(ByRef sheet As ISheet, ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal value As String)

    '空白のセルとかだとrow、cellがnullになるので、その対応
    Dim row As IRow = If(sheet.GetRow(rowIndex - 1), sheet.CreateRow(rowIndex - 1))
    Dim cell As ICell = If(row.GetCell(columnIndex - 1), row.CreateCell(columnIndex - 1))

    cell.SetCellValue(value)

End Sub

Private Sub WriteCell(ByRef sheet As ISheet, ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal value As Double)

    Dim row As IRow = If(sheet.GetRow(rowIndex - 1), sheet.CreateRow(rowIndex - 1))
    Dim cell As ICell = If(row.GetCell(columnIndex - 1), row.CreateCell(columnIndex - 1))

    cell.SetCellValue(value)

End Sub

Private Sub WriteCell(ByRef sheet As ISheet, ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal value As DateTime)

    Dim row As IRow = If(sheet.GetRow(rowIndex - 1), sheet.CreateRow(rowIndex - 1))
    Dim cell As ICell = If(row.GetCell(columnIndex - 1), row.CreateCell(columnIndex - 1))

    cell.SetCellValue(value)

End Sub

nice!(1)  コメント(0) 

継承したコントロールのTextの初期値を変更する [VB.NET]

Buttonを継承してカスタムコントロール(以下SearchButton)を作成した。
SearchButtonには虫眼鏡のアイコンを設定したけど、ツールボックスから配置すると
TextにSearchButton1と入ってしまう。
別にTextを削除すれば良いのだけど、最初から空白が入れば良いなと思ってコンストラクタで
MyBase.Textに空白を設定したけど空白にならなかった。

調べてみて次のコードで実現できた。
参照:System.Design.dll
Imports System.ComponentModel

Public Class ControlDesignerEx
    Inherits System.Windows.Forms.Design.ControlDesigner

    Public Overrides Sub InitializeNewComponent(ByVal defaultValues As System.Collections.IDictionary)
        MyBase.InitializeNewComponent(defaultValues)
        Me.Control.Text = ""
    End Sub
End Class

<Designer(GetType(ControlDesignerEx))>
Public Class SearchButton
    Inherits Button

    Public Sub New()
        MyBase.New()
        MyBase.Image = UserCtrl.My.Resources.Resources.SearchIcon
    End Sub
End Class


この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。