TIPS |
VB/Excel定番の関数をVB.netでも使う |
'Microsoft.VisualBasicをインポートする
Imports Microsoft.VisualBasic
Strings.Left
Strings.Right
Strings.Mid
|
[ビルド]OS標準でのMSBuildの場所 |
[Windows]¥Microsoft.NET¥Framework64¥v4.0.30319¥
[Windows]¥Microsoft.NET¥Framework¥v4.0.30319¥
|
[Debug]DataSetビジュアライザー |
1.クイックウォッチでDataSetを指定する。
2.Tables->Listプロパティを見る。
3.該当列(1つだけしかTableがないなら"(0)"の列)の値列の虫眼鏡をクリックする。
|
[Debug]DataTableビジュアライザー |
1.クイックウォッチでDataTableを指定する。
2.ツリーを展開しないで値列の虫眼鏡をクリックする。
|
標準出力に出力する |
Console.WriteLine("何かを出力")
|
app.configから値を取得する |
'[System.Configuration.dll]が必要
Dim value = System.Configuration.ConfigurationManager.AppSettings("キー")
|
プロセス起動 |
'起動する1(ProcessStartInfoオブジェクトあり)
Dim psInfo As New System.Diagnostics.ProcessStartInfo()
psInfo.FileName = "notepad.exe"
Dim process As System.Diagnostics.Process = System.Diagnostics.Process.Start(psInfo)
'起動する2
Dim process As System.Diagnostics.Process = System.Diagnostics.Process.Start("C:\test\1.txt")
'終わるまで待つ
process.WaitForExit()
|
app.configのサンプル(最小) |
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="キー" value="値" />
</appSettings>
</configuration>
|
[DataTable]各操作 |
Dim dt As DataTable = ds.Tables(0)
dt.Columns.Add("column_name") 'column_name列を追加
If IsNothing(dt) OrElse dt.Rows.Count = 0 Then
'なし(0件を含む)
End If
'Columnループ
For Each col As DataColumn In dt.Columns
Next 'dt.Columns
'Rowループ
For Each dr As DataRow In dt.Rows
If dt.Columns.Contains("column_name") Then
'列に"column_name"がある場合
'CStr(dr("column_name"))でも良いが、CStrはDBNullで落ちるらしい
Dim column_name = dr("column_name").ToString
End If 'exists column_name
Next 'dt.Rows
'データ追加
Dim dr As DataRow = dt.NewRow
dr.Item("field1") = "field1"
dt.Rows.Add(dr)
'データ追加 1行
dt.Rows.Add(New Object(){""}) 'Columnの数だけ必要
'検索 Select
Dim selectedRows As DataRow() = dt.Select("field1='a'")
|
[DataTable]各操作その2 |
'列情報だけをコピー
Dim dt2 = dt1.Clone
'列情報&データをコピー
Dim dt2 = dt1.Copy
'DataSetに繋がっていているDataTableをコピー
Dim ds1 As New DataSet
Dim dt1 As New DataTable("dt1")
ds1.Tables.Add(dt1)
Dim dt2 As DataTable
'dt2 = dt1 だと ds1 に繋がっているのでNG
dt2 = dt1.Copy
'DataRow単位(丸ごと)コピー
dt1 (データが入っている前提)
Dim dt2 = dt1.Clone
'dt2.Rows.Add(dt1.Rows(0)) は繋がっているのでNG
dt2.ImportRow(dt1.Rows(0))
|
ファイル削除 |
System.io.File.Delete(削除するファイル) 'ファイルがなくてもエラーにならない
|
Option |
Option Strict On '暗黙的な型変換を禁止する
Option Infer On '型推論を有効にする(StrictをOnにしていても大丈夫)
|
[DataTable]移替え |
Dim convertMap As Hashtable = New Hashtable From {
'取得先, 取得元
{"a","A"},
{"b","B"},
}
Private Function ConvDatatable(ByVal pConvMap As Hashtable, ByVal pDt As DataTable) As Datatable
Dim newDt As DataTable = New Datatable
'+-- 列を追加
For Each key In pConvMap.Keys
newDt.Column.Add(key)
Next
'+-- 移し替え
For Each dr As DataRow In pDt.Rows
Dim newDr As DataRow = newDt.Rows.Add
For Each key In pConvMap.Keys
Dim from_key = pConvMap(key).ToString
If(pDt.Column.Contains(from_key))Then
newDr(key) = dr(from_key)
End If
Next
Next
Return newDt
End Function
|
[関数]DataTableからCSVファイル作成 |
Public Sub BuildCsvFileFromDataTable(ByVal pFilepath As String, ByVal pDt As DataTable, Optional ByVal isHeader As Boolean = False)
Using(writer = StreamWrtier(pFilepath, True))
Dim output = New StringBuilder
Dim first = True
'+--
If(isHeader)Then
output = New StringBuilder
For Each col In pDt.Columns
If(first)Then
output.Append(col.Name)
first = False
Else
output.Append(",").Append(col.Name)
End If
Next
writer.WriteLine(output.ToString)
End If
'+--
For Each dr As DataRow In pDt.Rows
output = New StringBuilder
first = True
For idx As Integer = 0 To pDt.Columns.Count -1
If(first)Then
output.Append(dr(idx))
first = False
Else
output.Append(",").Append(dr(idx))
End If
Next
writer.WriteLine(output.ToString)
Next 'pDt.Rows
writer.Flush
End Using
End Sub
|
ファイルパスを構成する |
'+-- ファイルパスを構成する[folder¥file(win) or folder/file(win以外)]
Dim filepath = IO.Path.Combine(folder, file)
|
CSVファイル(TextFieldParser) |
'-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
' CSVファイルの読み込み
' デリミタを変更すれば[TAB]でも可能
' 以下のデータでも問題なく(3列で)読み取りできる
' "aaa",bbb,"cc,cc"
' データに改行が入る場合は[CSVHelper]に変更することを検討する
'-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Import Microsoft.VisualBasic.FileIO
Dim filepath = IO.Path.Combine("folder", "filename")
Using reader As New TextFieldParser(filepath)
reader.Delimiters = New String() {","}
While Not reader.EndOfData
Dim fields = reader.ReadFields()
End While
End Using
|
ファイル操作 |
'+-- ファイル存在チェック
If IO.File.Exists(filepath) Then
'ファイルがあるとき
End If
'+-- ファイル削除
System.IO.File.Delete(filepath) 'ファイルがないとエラー
My.Computer.FileSystem.DeleteFile(filepath) 'ファイルがないとエラー
New System.IO.FileInfo(filepath).Delete() 'ファイルがなくてもエラーにならない
'+-- ファイルコピー
IO.File.Copy(fromfile, tofile)
'+-- ファイル移動(名称変更も同様)
IO.File.Move(fromfile, tofile)
|
XML読み込み(LINQバージョン) |
' XMLの読み込み
Dim xmlElement As XElement = XElement.Load("hogehoge.xml")
' LINQのクエリ(hogeで始まるName)
Dim query = From elem In xmlElement.Elements("Userinfo") Where elem.Element("Name").Value Like "hoge*"
' 結果表示
For Each elem In query
Console.WriteLine($"name:{elem.Element("Name").Value}, age{elem.Element("Age").Value}")
Next
' LINQのクエリ(Ageが30より大きい)
query = From elem In xmlElement.Elements("Userinfo") Where Integer.Parse(elem.Element("Age").Value) > 30
' 結果表示
For Each elem In query
Console.WriteLine($"name:{elem.Element("Name").Value}, age{elem.Element("Age").Value}")
Next
|
[関数]CSV2DataTable |
Import Microsoft.VisualBasic.FileIO
Function ConvCsvFileToDataTable(ByVal pFileName As String) As DataTable
Dim dt As DataTable = New DataTable
Using reader As New TextFieldParser(pFileName)
reader.Delimiters = New String() {","}
Dim first As bolean = True
While Not reader.EndOfData
Dim fields = reader.ReadFields()
If first Then
'ヘッダ行
Dim index As Integer = 0
For Each s In fields
index = index + 1
If Not String.IsNullOrEmpty(s) AndAlso Not dt.Columns.Contains(s) Then
dt.Columns.Add(s)
Else
dt.Columns.Add("field" & index)
End If
Next
Else
'データ行
Dim dr As DataRow = dt.Rows.Add
Dim index As Integer = 0
For index = 0 To fields.Count - 1
dr(index) = fields(index)
Next
End If
End While
End Using
Return dt
End Function
|
Moduleサンプル(with log4net) |
Imports System.IO
Imports System.Text
<Assembly: log4net.Config.XmlConfigurator(ConfigFileExtension:="log4net", Watch:=True)<
Module Sample
Private ReadOnly logger As log4net.ILog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)
Sub Main(ByVal args As String())
logger.Info("=== 処理開始 ===")
'+--
If(args.Length = 0) Then
'+-- 引数なしは終了
System.Environment.ExitCode = 0
Return
End If
'+-- EXEパスを取得
Dim currentDir As String = Directory.GetParent(System.Reflection.Assembly.GetExecutingAssembly().Location).ToString
System.Environment.ExitCode = 0
logger.Info("=== 処理終了 ===")
End Sub
End Module
|
vbprojサンプル |
<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- 設定 -->
<PropertyGroup>
<AssemblyName>アプリケーション名</AssemblyName>
<RootNamespace>ルートのNamespace名</RootNamespace>
<OutputType>Exe</OutputType>
<Platform>AnyCPU</Platform>
<OutputType>Exe</OutputType>
<Configuration>Debug</Configuration>
<OutputPath>bin</OutputPath>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
</PropertyGroup>
<!-- デフォルトimports -->
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Diagnostics" />
</ItemGroup>
<!-- 参照設定 -->
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>bin¥log4net.dll</HintPath>
</Reference>
</ItemGroup>
<!-- リソース(プログラムソースなど) -->
<ItemGroup>
<Compile Include="プログラム.vb" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project>
|
[発行]を行うためのprojectファイル |
XXXX_Publish.xmlに発行の設定が出力される。
|
参照渡ししても呼び元に値が反映されないケース |
参照渡しはポインタを渡します。
呼び出し先でポインタを変えてしまうと、呼び元には反映されません。
'呼び出し
Dim ds As New DataSet 'ポインタA
Call subA(ds)
Sub subA(ByRef pDs)
Dim tmpDs As New DataSet 'ポインタB
tmpDs.Tables.Add(New DataTable)
pDs = tmpDs '引数への値の代入(ポインタの変更)はできない
'以下は反映される(ポインタAが変更されていないから)
'pDs.Tables.Add(New DataTable)
End Sub
ByRefでオブジェクト型を渡した際にできることとできないこと
できる
プロパティ変更、メソッド呼び出し
できない
新しいインスタンスの割り当て(ポインタの変更)
※たちが悪いことにコンパイルエラーにならない
上記で理解できない方は以下のサイトもご参照ください。
https://dobon.net/vb/dotnet/beginner/byvalbyref.html#google_vignette
残念なことにMSの解説は配列の説明までは記載されていますが、
オブジェクト型の場合にどのようになるのかは解説されていません。
配列を説明していることによって、逆にオブジェクト型の説明も含まれているように見えてしまいます。
しかも、この配列の説明で全体を代入(a = k)しているのでタチが悪いです。
https://learn.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/language-features/procedures/how-to-change-the-value-of-a-procedure-argument
|
リフレクション |
[DLLロード]
Dim a As [Assembly] = Refrection.[Assembly].Load("DLL名")
[型]
Dim t As Type = a.GetType("DLL名.クラス名")
[メンバに設定]
t.Invoke("メンバ", BindingFlag, Nothing, <クラスインスタンス>, New Object() {"値"})
[メソッド呼び出し]
t.Invoke("メソッド名", InvokeMethod, Nothing, <クラスインスタンス>, New Object(){})
|