RunningCSharp

MS系開発者による、雑多な記事。記事は所属企業とは関係のない、個人の見解です。

VBA UTF-8のテキストファイルをソートして出力する

任意のテキストファイル(UTF-8)の内容を行単位で昇順ソートし、元のファイルに書き戻すコード例。

Public Sub SortText()

    Dim strarr() As String
    Dim strall As String
    'ファイル名、任意の内容を指定
    Dim filename As String: filename = "filepath(ex:C:\test\testflie.txt)"
    Dim strsave As Variant
    
    'ファイル読み込み(UTF-8はADODB.Streamを使うほかなさそう)
    Dim adodb As Object: Set adodb = CreateObject("ADODB.Stream")
    adodb.Charset = "UTF-8"
    adodb.Open
    adodb.LoadFromFile filename
    strall = adodb.ReadText
    adodb.Close
    
    '以下は対象ファイルの改行がLFの例。CRLFの場合はvbCrLfを使用する。
    strarr = Split(strall, vbLf)
    'ソート
    SortArray strarr
    '保存
    adodb.Open
    For Each strsave In strarr
        adodb.WriteText strsave & vbLf, 0
    Next
    adodb.SaveToFile filename, 2
    adodb.Close

End Sub
'配列引数arrのソートを実施
Private Sub SortArray(ByRef arr() As String)
    Dim arrCount As Integer
    Dim sortCount As Integer
    Dim strBuf As String
    
    For arrCount = 0 To UBound(arr)
        For sortCount = arrCount + 1 To UBound(arr)
            If arr(arrCount) > arr(sortCount) Then
            strBuf = arr(arrCount)
            arr(arrCount) = arr(sortCount)
            arr(sortCount) = strBuf
            End If
        Next sortCount
    Next arrCount
End Sub

下記のようなファイルを指定し実行すると、

c
d
f
3
1
ぬ
5
@

下記のようにソートされる。

@
1
3
5
c
d
f
ぬ

PowerShell テキストファイルをソートして出力する

同フォルダのUTF-8のテキストファイル「output.txt」の内容を行単位で文字コード昇順でソートし、「output2.txt」に出力する例

Get-Content -Encoding UTF8 -Path "./output.txt" | Sort-Object | Set-Content  -Encoding UTF8 "./output2.txt" 

降順だと以下の通り。

Get-Content -Encoding UTF8 -Path "./output.txt" | Sort-Object -Descending | Set-Content  -Encoding UTF8 "./output2.txt" 

上記ソートのPowerShellコマンドをコマンドプロンプトから実施させる場合、以下のようにbatファイルを作成。(昇順の例)

test.bat

powershell -Command "Get-Content -Encoding UTF8 -Path './output.txt' | Sort-Object | Set-Content  -Encoding UTF8 './output2.txt'" 

「output.txt」に下記のような内容を格納し実行すると、

c
d
f
3
1
ぬ
5
@

「output2.txt」は下記のように出力される。

@
1
3
5
c
d
f
ぬ

VB(.net) Windows10 WinForms・DataGridViewのColumnHeaderのソートを示す三角だけ操作する

記のようなコードを実行した際、右側のカラムをクリックした際、ソートはされないがソートを示す三角形が「昇順→降順→ソートなし」の順に変化する。

コード

Imports System.ComponentModel

Public Class Form1
    'ソートの状態を保存する変数
    Dim sordOrder As SortOrder = SortOrder.None

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

        '以下はDataGridViewのデータ表示用コード
        Dim table As DataTable = New DataTable()

        table.Columns.Add("col1")
        table.Columns.Add("col2")
        table.Rows.Add({1, 1})
        table.Rows.Add({2, 2})
        table.Rows.Add({4, 4})
        table.Rows.Add({3, 3})
        DataGridView1.DataSource = table

        '自動ソートを停止
        DataGridView1.Columns.Item(1).SortMode = DataGridViewColumnSortMode.Programmatic

    End Sub

    Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
        '右側のカラムでのみ、「ソートなし」処理を実装
        If e.ColumnIndex = 1 Then
            Dim vc As DataGridViewColumn = DataGridView1.Columns.Item(e.ColumnIndex)
            'すでにソート中であれば、次のソート状態を保持
            sordOrder = GetNextOrder(sordOrder)

            '※データの独自ソートを行いたい場合は、ここでデータのソートを実施


            'カラムヘッダーの矢印を現在のソート状態に合わせる
            vc.HeaderCell.SortGlyphDirection = sordOrder

        End If

    End Sub

    'ソート順を受け取り、次のソート順を返す
    Private Function GetNextOrder(sortOrder As SortOrder) As SortOrder
        Dim rtn As SortOrder
        Select Case sortOrder
            Case SortOrder.Ascending
                rtn = SortOrder.Descending
            Case SortOrder.Descending
                rtn = SortOrder.None
            Case SortOrder.None
                rtn = SortOrder.Ascending
        End Select
        Return rtn
    End Function

End Class

f:id:ys-soniclab:20190119215201p:plain
クリック一回目

f:id:ys-soniclab:20190119215217p:plain
クリック二回目

f:id:ys-soniclab:20190119215232p:plain
クリック三回目

VB(.net) Windows10 WinForms・DataGridViewのカラムクリック時、「昇順→降順→ソートなし」の順となるようカスタム

デフォルトのDataGridViewはカラムをクリックすると、「昇順→降順」の順にソートされる。 この挙動を、「昇順→降順→ソートなし」となるようカスタムする。 下記例では、右側のカラムのみカスタムが実装される。

Imports System.ComponentModel

Public Class Form1
    'ソートの状態を保存する変数
    Dim sordOrder As SortOrder = SortOrder.None

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

        '以下はDataGridViewのデータ表示用コード
        Dim table As DataTable = New DataTable()

        table.Columns.Add("col1")
        table.Columns.Add("col2")
        table.Rows.Add({1, 1})
        table.Rows.Add({2, 2})
        table.Rows.Add({4, 4})
        table.Rows.Add({3, 3})
        DataGridView1.DataSource = table

    End Sub

    Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
        '右側のカラムでのみ、「ソートなし」処理を実装
        If e.ColumnIndex = 1 Then
            Dim vc As DataGridViewColumn = DataGridView1.Columns.Item(e.ColumnIndex)
            'すでにソート中であれば、次のソート状態を保持
            sordOrder = GetNextOrder(sordOrder)

            If sordOrder = SortOrder.None Then
                'ソート状態をリセット
                DataGridView1.DataSource.DefaultView.Sort = String.Empty
            Else
                'ソートを実行
                DataGridView1.Sort(vc, IIf(sordOrder = SortOrder.Ascending, ListSortDirection.Ascending, ListSortDirection.Descending))
            End If

        End If

    End Sub

    'ソート順を受け取り、次のソート順を返す
    Private Function GetNextOrder(sortOrder As SortOrder) As SortOrder
        Dim rtn As SortOrder
        Select Case sortOrder
            Case SortOrder.Ascending
                rtn = SortOrder.Descending
            Case SortOrder.Descending
                rtn = SortOrder.None
            Case SortOrder.None
                rtn = SortOrder.Ascending
        End Select
        Return rtn
    End Function

End Class

f:id:ys-soniclab:20190119214313p:plain
クリック一回目

f:id:ys-soniclab:20190119214333p:plain
クリック二回目

f:id:ys-soniclab:20190119214349p:plain
クリック三回目

VB(.net) Windows10 WinForms・DataGridViewのColumnHeaderのソートを示す三角が見えなくなる

下記のようなコードを実行した際、右側のカラムにて、ColumnHeaderのソート順を示す三角形が表示されなくなる。

コード

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

        DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
        DataGridView1.ColumnHeadersHeight = 20

        DataGridView1.Columns.Add("col1", "1")
        DataGridView1.Columns.Add("col2", "2222222222")
        DataGridView1.Rows.Add({1, 3})
        DataGridView1.Rows.Add({2, 4})

       DataGridView1.Columns().Item(1).Width = 110

    End Sub
End Class

実行結果

f:id:ys-soniclab:20190103185521p:plain
左側カラムでソート実施

f:id:ys-soniclab:20190103185545p:plain
右側カラムでソート実施

2枚目のスクリーンショットでは、右側のカラムでソートを実施しているが、ヘッダーに三角形が表示されない。 本問題は、文字がカラムいっぱいに広がることで、ソートを示す三角形が消えてしまうことで発生する。 カラムを広げる調整を行うことで、問題を回避できる。

コード

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

        DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
        DataGridView1.ColumnHeadersHeight = 20

        DataGridView1.Columns.Add("col1", "1")
        DataGridView1.Columns.Add("col2", "2222222222")
        DataGridView1.Rows.Add({1, 3})
        DataGridView1.Rows.Add({2, 4})

        '以下を追加
        DataGridView1.Columns().Item(1).Width = 110

    End Sub
End Class

実行結果

f:id:ys-soniclab:20190103190025p:plain
コード変更後

VB(.net) Windows10 WinFormsのDataGridViewのカスタム

本記事では、下記の方法をまとめて記載いたします。(挙動はWindows10にて確認済の内容となります)

①DataGridViewのヘッダー背景色変更

②DataGridViewのヘッダー文字色変更

③DataGridViewのヘッダー・項目それぞれのフォント変更

④DataGridViewのヘッダー・項目それぞれの文字の寄せ方変更

変更前のコードと画面は以下の通り。

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

        DataGridView1.Columns.Add("col1", "漢字1")
        DataGridView1.Columns.Add("col2", "漢字2")
        DataGridView1.Rows.Add({"漢字3", 3})
        DataGridView1.Rows.Add({"漢字4", 4})

    End Sub
End Class

f:id:ys-soniclab:20181231204739p:plain
変更前

変更用コードと変更後画面は以下の通り。

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

        DataGridView1.Columns.Add("col1", "漢字1")
        DataGridView1.Columns.Add("col2", "漢字2")
        DataGridView1.Rows.Add({"漢字3", 3})
        DataGridView1.Rows.Add({"漢字4", 4})

        '下記設定を行わないと、①と②の設定が反映されない
        DataGridView1.EnableHeadersVisualStyles = False

        '①DataGridViewのヘッダー背景色変更
        DataGridView1.Columns().Item(0).HeaderCell.Style.BackColor = Color.Red
        '②DataGridViewのヘッダー文字色変更
        DataGridView1.Columns().Item(1).HeaderCell.Style.ForeColor = Color.Green

        '③DataGridViewのヘッダー・項目それぞれのフォント変更
        'ヘッダーのフォント変更
        DataGridView1.Columns().Item(0).HeaderCell.Style.Font = New Font("MS 明朝", 8)
        DataGridView1.Columns().Item(1).HeaderCell.Style.Font = New Font("Meiryo UI", 15)
        '項目のフォント変更
        DataGridView1.Columns().Item(0).DefaultCellStyle.Font = New Font("MS ゴシック", 15)
        DataGridView1.Columns().Item(1).DefaultCellStyle.Font = New Font("MS P ゴシック", 8)

        '④DataGridViewのヘッダー・項目それぞれの文字の寄せ方変更
        'ヘッダーの寄せ方変更
        DataGridView1.Columns().Item(0).HeaderCell.Style.Alignment = DataGridViewContentAlignment.TopLeft
        DataGridView1.Columns().Item(1).HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomLeft

        '項目の寄せ方変更
        DataGridView1.Columns().Item(0).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
        DataGridView1.Columns().Item(1).DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomRight

        'ヘッダーの高さ変更
        '下記のプロパティ変更を行わないと、ColumnHeadersHeightが正しく反映されない
        DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
        DataGridView1.ColumnHeadersHeight = 100

    End Sub
End Class

f:id:ys-soniclab:20190103184425p:plain
変更後

VBでASP.net WebAPIを作る

ASP.net+VBでWebApiを作りたい。WebApiは呼ばれたらバッチを実行し、バッチ処理が完了した後にレスポンスを返してほしい。レスポンスは何でもよい。」とリクエストを受けたので、作ってみました。

WebApiの作り方は、下記の記事内容を引用させて頂きます。

blog.okazuki.jp

本記事は、ほとんど上記記事のコードをVBでやってみただけの記事になります。

プロジェクトを作る

空のASP.netプロジェクトを作成します。

f:id:ys-soniclab:20170204210936p:plain

NuGetで「Microsoft ASP.NET Web API 2 Web Host」を追加

f:id:ys-soniclab:20170204211017p:plain

本記事ではv5.2.3を利用しました。

Global.asaxの追加

プロジェクトを右クリックし、「追加」→「新しい項目を追加」を選択し、ダイアログで「Web」→「グローバル アプリケーション クラス」を選択。

f:id:ys-soniclab:20170204211129p:plain

作成された「Global.asax」を開き、下記のようにコードを追加します。

Imports System.Web.SessionState
'追加ここから
Imports System.Web.Http
'追加ここまで

Public Class Global_asax
    Inherits System.Web.HttpApplication

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' アプリケーションの起動時に呼び出されます
        '追加ここから
        GlobalConfiguration.Configure(
            Sub(config)
                config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}",
                                           New With {.id = RouteParameter.Optional})
            End Sub)
        '追加ここまで
    End SubEnd Class

ControllerフォルダとControllerクラスの追加

プロジェクトを右クリックし、「追加」→「新しいフォルダー」でフォルダを追加、名前を「Controller」に変更します。 「Controller」フォルダを右クリックし、「追加」→「クラス」でクラスを追加する、名前は「ExecBatchController」とします。

f:id:ys-soniclab:20170204212746p:plain

メソッドの実装

ExecBatchControllerを下記のように書き換えます。 なお、C#ではGetのWebAPIを作成する場合「Get」とするが、VBでは「Get」が予約語であるため、「GetValues」とします。

Imports System.Web.Http

Public Class ExecBatchController
    Inherits ApiController

    Public Function GetValues() As String

        'バッチを実行(test.batはtimeout 20を実行する)
        Dim p As System.Diagnostics.Process =
            System.Diagnostics.Process.Start("C:\\test\\test.bat")
        p.WaitForExit()
        '適当な値を返す
        Return "end process"
    End Function

End Class

実行

実行すると、ブラウザにはエラーが表示されるが、WebAPIは起動しています。

f:id:ys-soniclab:20170204214346p:plain

ブラウザのアドレスバーに「http://localhost:(ポートNo)/api/ExecBatch」と入力すると、バッチが実行されます。

f:id:ys-soniclab:20170204214326p:plain

バッチ終了後、"end process"と文字列が返されます。

f:id:ys-soniclab:20170204214747p:plain