C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: ListBoxに表示する文字列を揃える方法


(過去ログ 178 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■101955 / inTopicNo.1)  ListBoxに表示する文字列を揃える方法
  
□投稿者/ 初心者 (4回)-(2023/05/19(Fri) 14:08:14)

分類:[VB.NET/VB2005 以降] 

VB初心者です。

VB2005 .NETでwindowsアプリケーションを作成しています。
ファイルデータの中から特定の情報のみを抽出して、左揃えでListBoxに表示させたいです。
SHIFT-JISやUNICODE、UTFなどの様々な文字コードが混在しており、上手く左揃えで表示できません。

様々な文字コードが混在しているデータを揃えてListBoxに表示させる方法を教えてください。
引用返信 編集キー/
■101956 / inTopicNo.2)  Re[1]: ListBoxに表示する文字列を揃える方法
□投稿者/ 魔界の仮面弁士 (3646回)-(2023/05/19(Fri) 14:14:19)
2023/05/19(Fri) 14:37:05 編集(投稿者)

No101955 (初心者 さん) に返信
> SHIFT-JISやUNICODE、UTFなどの様々な文字コードが混在しており、上手く左揃えで表示できません。
文字コードは関係ないのでは?
文字集合(CharSet)なら関係するかもしれませんが。


それに「上手く左揃えで表示できません」とだけ仰られても、
それがどういう状態になっていて、それをどうしたいのかが
一切説明されていないので、具体的な対策を答えるのは難しいです。

たとえば WinForms において ListBox1.Items.Add("文字列") と書いた場合
MultiColumn が True / False のいずれであったとしても、
それぞれの項目は既定で左寄せで記述されるはずなので、
「うまく表示できない」が何を指しているのかが曖昧です。
https://www.itlab51.com/?p=2912


> 様々な文字コードが混在しているデータを揃えてListBoxに表示させる方法を教えてください。
String 型の内部データの文字コードは UTF-16 相当で固定です。

タブやスペースなどで区切った複数列表示にしたいという事でしょうか?
その場合は、ListBox 以外のコントロール
(たとえば ListView の Details モードなど)を使うことを
検討してみた方が良いと思います。

あるいは固定幅フォントを用いるようにしたうえで、
文字幅(いわゆる半角/全角の類)を考慮した文字列を用意するか、
あるいはオーナードローするとか。
http://hanatyan.sakura.ne.jp/vb2005/vb2013listbox04.htm
引用返信 編集キー/
■101957 / inTopicNo.3)  Re[1]: ListBoxに表示する文字列を揃える方法
□投稿者/ kiku (346回)-(2023/05/19(Fri) 14:31:31)
No101955 (初心者 さん) に返信
> VB初心者です。
>
> VB2005 .NETでwindowsアプリケーションを作成しています。
> ファイルデータの中から特定の情報のみを抽出して、左揃えでListBoxに表示させたいです。
> SHIFT-JISやUNICODE、UTFなどの様々な文字コードが混在しており、上手く左揃えで表示できません。
>
> 様々な文字コードが混在しているデータを揃えてListBoxに表示させる方法を教えてください。

1つのファイルの中身が、文字コードが混在されている状態なのでしょうか?
その場合、そのファイルをバイナリで読み取ってから、
ここから、ここまでは、UTF8、
ここから、ここまでは、シフトJISなどの
ファイルとしてのルールなどがあり、
適宜適切な文字コードで取り込んでいるのでしょうか?

あまり、そんなファイルを扱ったことがないので確認です。
引用返信 編集キー/
■101958 / inTopicNo.4)  Re[2]: ListBoxに表示する文字列を揃える方法
□投稿者/ 初心者 (5回)-(2023/05/19(Fri) 15:22:39)
魔界の仮面弁士、kiku さん返信ありがとうございます。

説明不足ですみません。
複数のファイルからデータ(名前や地名、番号など)を読みだしてきています。
データが英語やハングル、中国語など様々な言語で管理されています。
例、個人001.dat(英語) 個人002.dat(日本語) 個人003.dat(中国語) ...
下記サイトを参考に空白埋めで揃えようとしています。
http://hanatyan.sakura.ne.jp/dotnet/StrCut.htm

<現状>
個人001 : aaa abc 25
個人002 : bbb あああ 75
個人003 : ccc 哦哦哦 66

<やりたいこと>
個人001 : aaa abc 25
個人002 : bbb あああ 75
個人003 : ccc 哦哦哦 66
引用返信 編集キー/
■101959 / inTopicNo.5)  Re[3]: ListBoxに表示する文字列を揃える方法
□投稿者/ 魔界の仮面弁士 (3647回)-(2023/05/19(Fri) 16:36:09)
2023/05/19(Fri) 16:56:19 編集(投稿者)

No101958 (初心者 さん) に返信
> 下記サイトを参考に空白埋めで揃えようとしています。
> http://hanatyan.sakura.ne.jp/dotnet/StrCut.htm
それは Shift_JIS の文字集合に収録されている文字のみを対象とした手法です。
日本語環境を前提としたものであり、他言語環境で通用する手法ではありません。

たとえば Unicode には「ゼロ幅文字」というものが存在しますが、それには非対応です。
同じ文字であっても、文章の先頭に来た場合と
二文字目以降に来た場合で文字幅が異なる言語なんてもありますしね。

あるいは、
 TextBox1.Text = ChrW(&HD842) & ChrW(&HDFB7) & ChrW(&H91CE) & ChrW(&H5BB6)
 TextBox2.Text = ChrW(&H5409) & ChrW(&H91CE) & ChrW(&H5BB6)
のような文字列の桁位置合わせにも向かないでしょう。(両者はいずれも漢字 3 文字)

また、『┠』や『α』といった文字は、日本語向けフォントでは
全角相当でレンダリングされることが多いですが、他国語対応フォントでは
半角相当でレンダリングされる可能性があります。


なので空白でそろえるのではなく、先ほどの回答でも述べたように、
ListBox を使う代わりに、1 行を複数の列で表示できるコントロール
(ListView など)に変更するか、あるいはオーナードローなどで
対処することをお奨めします。
http://hanatyan.sakura.ne.jp/vb2005/vb2013listview01.htm

> データが英語やハングル、中国語など様々な言語で管理されています。
元データの「文字コード」が混在しているわけではないですよね?


たとえば、文字集合としての Unicode であれば、
同一の文字コード(UTF-7 とか UTF-8 とか UTF-16LE とか)にて、
それらの文字種を同時に扱えます。

厳密にいえば Unicode バージョンによって収録している文字数が異なりますし、
Unicode 未収録の文字(たとえば日本の戸籍統一文字の一部など)もあるので、
複数の文字コードを併用して管理することが無いとは言えませんけれどね…。

-- 以下蛇足 --
たとえば韓国語の場合、ハングル自体は 24 種(子音14個+母音10個)ですが、
それらの組み合わせで一つの文字を表すため、文字種そのものは 11,172個あります。
しかし日常で使う文字は3〜4千字程度なので、韓国系文字コードでは
よく使われるハングルしか収録されていません。

韓国の Wansung (KS X 1001:2002) に収録されている文字数は
8227文字(ハングル2350字、漢字4888字、その他989)です。
これには 平仮名(83文字)や片仮名(86文字)なども含まれています。


中文漢字向けの物で見てみると、
GB 18030-2022 で 87,887文字
GB 18030-2005 で 70,244文字
という収録状況です。

ちなみに VB6 当時の Unicode は UCS-2 相当の符号化を想定しており、
最大でも基本多言語面の 65,536 文字種しか保持できませんでした。

現在の VB ではサロゲートペアや UTF-8 をサポートしたので、
Unicode の基本多言語面外の文字を扱えるようになっています。
(絵文字サポートなどは、WPF と WinForm で状況が異なるのですけれど)

Unicode 2.0 で 38,950文字を収録
Unicode 3.2 で 95,221文字を収録(JIS X 0213 に正式対応)
Unicode 15.0 で 149,186文字を収録
引用返信 編集キー/
■101960 / inTopicNo.6)  Re[4]: ListBoxに表示する文字列を揃える方法
□投稿者/ 魔界の仮面弁士 (3648回)-(2023/05/19(Fri) 18:12:58)
No101959 (魔界の仮面弁士) に追記
> なので空白でそろえるのではなく、先ほどの回答でも述べたように、
> ListBox を使う代わりに、1 行を複数の列で表示できるコントロール
> (ListView など)に変更するか、あるいはオーナードローなどで
> 対処することをお奨めします。
> http://hanatyan.sakura.ne.jp/vb2005/vb2013listview01.htm

ListBox の代わりに ListView を使ってみるサンプル。


Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  ' このあたりはデザイン時に指定しておけばよい
  ListView1.View = View.Details
  ListView1.FullRowSelect = True
  ListView1.GridLines = False
  ListView1.Columns.Add("列1")
  ListView1.Columns.Add("列2")
  ListView1.Columns.Add("列3")
  ListView1.Columns.Add("列4").TextAlign = HorizontalAlignment.Right
  ListView1.HeaderStyle = ColumnHeaderStyle.Nonclickable
  'ListView1.HeaderStyle = ColumnHeaderStyle.None '列ヘッダが不要な場合


  'データ登録
  ListView1.Items.Add("個人001").SubItems.AddRange(New String() {"aaa", "abc", "25"})
  ListView1.Items.Add("個人002").SubItems.AddRange(New String() {"bbb", "あああ", "75"})
  ListView1.Items.Add("個人003").SubItems.AddRange(New String() {"ccc", "哦哦哦", "66"})
End Sub
引用返信 編集キー/
■101961 / inTopicNo.7)  Re[3]: ListBoxに表示する文字列を揃える方法
□投稿者/ KOZ (404回)-(2023/05/19(Fri) 19:26:13)
2023/05/19(Fri) 23:37:30 編集(投稿者)
No101958 (初心者 さん) に返信
> <やりたいこと>
> 個人001 :  aaa    abc          25
> 個人002 :  bbb    あああ       75
> 個人003 :  ccc    哦哦哦       66

ゼロ幅スペースやサロゲートペアなどを考えると幅を求めるのは結構やっかいです。
面倒なことは知ってる人にやらせてみます。(つまり GDI に聞く。)
描画領域には余白があるので最初に半角2文字の幅から半角1文字の幅を引いて
1文字あたりの幅を求めます。残りが余白になるのでそれをもとに判定していきます、

Imports System.Globalization

Public Class Form1

    Private _Graphics As Graphics = Graphics.FromHwnd(IntPtr.Zero)
    Private _FixedFont As New Font("MS ゴシック", 9.75!, FontStyle.Regular)
    Private _HalfCharWidth As Integer
    Private _Padding As Integer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim twoCharWidth As Integer = GetDrawWidth("AA")
        Dim oneCharWidth As Integer = GetDrawWidth("A")
        _HalfCharWidth = twoCharWidth - oneCharWidth
        _Padding = twoCharWidth - _HalfCharWidth
        ListBox1.Font = _FixedFont
        ListBox1.Items.Clear()
        ListBox1.Items.Add(EditItem("個人001", "aaa", "abc", "25"))
        ListBox1.Items.Add(EditItem("個人002", "bbb", "あああ", "75"))
        ListBox1.Items.Add(EditItem("個人003", "ccc", "哦哦哦", "66"))
    End Sub

    Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
        _Graphics.Dispose()
        _Graphics = Nothing
        _FixedFont.Dispose()
        _FixedFont = Nothing
    End Sub

    Private Function EditItem(item1 As String, item2 As String, item3 As String, item4 As String) As String
        Return RightPad(item1, 8) & ":  " & RightPad(item2, 7) & RightPad(item3, 13) & item4
    End Function

    Private Function GetDrawWidth(text As String) As Integer
        Return TextRenderer.MeasureText(_Graphics, text, _FixedFont).Width
    End Function

    Private Function RightPad(text As String, nLength As Integer) As String
        Dim drawWidth As Integer = GetDrawWidth(text)
        Dim needWidth As Integer = nLength * _HalfCharWidth + _Padding '必要な長さ
        If drawWidth > needWidth Then
            '必要な長さになるまで末尾を削る
            Dim info As New StringInfo(text)
            Dim length As Integer = info.LengthInTextElements - 1
            While drawWidth > needWidth
                text = info.SubstringByTextElements(0, length)
                drawWidth = GetDrawWidth(text)
                length -= 1
            End While
        End If
        Return text & New String(" "c, (needWidth - drawWidth) \ _HalfCharWidth)
    End Function

End Class

引用返信 編集キー/
■101963 / inTopicNo.8)  Re[3]: ListBoxに表示する文字列を揃える方法
□投稿者/ radian (129回)-(2023/05/22(Mon) 10:09:46)
2023/05/22(Mon) 11:33:21 編集(投稿者)
No101958 (初心者 さん) に返信
> データが英語やハングル、中国語など様々な言語で管理されています。
> 例、個人001.dat(英語) 個人002.dat(日本語) 個人003.dat(中国語) ...
> 下記サイトを参考に空白埋めで揃えようとしています。
> http://hanatyan.sakura.ne.jp/dotnet/StrCut.htm
> 
> <現状>
> 個人001 :  aaa    abc  25
> 個人002 :  bbb    あああ      75
> 個人003 :  ccc     哦哦哦   66
> 
> <やりたいこと>
> 個人001 :  aaa    abc          25
> 個人002 :  bbb    あああ       75
> 個人003 :  ccc    哦哦哦       66

空白埋めで揃えるというアプローチがそもそも間違っているので、
表っぽくしたいならDataGridViewか、弁士さんの別解にあるListViewでも使った方がいいと思います。


    Protected Overrides Sub OnLoad(e As EventArgs)
        MyBase.OnLoad(e)

        'DataGridView設定(ListBox風)
        DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
        'DataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None ←セル境界線が要らないなら設定
        DataGridView1.ColumnHeadersVisible = False
        DataGridView1.RowHeadersVisible = False
        DataGridView1.AllowUserToResizeColumns = False
        DataGridView1.AllowUserToResizeRows = False
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.ReadOnly = True
        DataGridView1.MultiSelect = False '複数行選択したいならTrue

        'DataGridView行を作る
        DataGridView1.Columns.AddRange({
            New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col1", .Width = 50},
            New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col2", .Width = 50},
            New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col3", .Width = 50},
            New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col4", .Width = 50}
        })

        'DataTableを作成し、DataGridViewに設定
        Dim dt As New DataTable
        dt.Columns.Add("Col1")
        dt.Columns.Add("Col2")
        dt.Columns.Add("Col3")
        dt.Columns.Add("Col4")
        dt.Rows.Add({"個人001", "aaa", "abc", "25"})
        dt.Rows.Add({"個人002", "bbb", "あああ", "75"})
        dt.Rows.Add({"個人003", "ccc", "哦哦哦", "66"})
        DataGridView1.DataSource = dt

    End Sub

引用返信 編集キー/
■101977 / inTopicNo.9)  Re[4]: ListBoxに表示する文字列を揃える方法
□投稿者/ 初心者 (6回)-(2023/05/23(Tue) 14:00:48)
No101963 (radian さん) に返信
> 2023/05/22(Mon) 11:33:21 編集(投稿者)
>
> ■No101958 (初心者 さん) に返信
>>データが英語やハングル、中国語など様々な言語で管理されています。
>>例、個人001.dat(英語) 個人002.dat(日本語) 個人003.dat(中国語) ...
>>下記サイトを参考に空白埋めで揃えようとしています。
>>http://hanatyan.sakura.ne.jp/dotnet/StrCut.htm
>>
>><現状>
>>個人001 : aaa abc 25
>>個人002 : bbb あああ 75
>>個人003 : ccc 哦哦哦 66
>>
>><やりたいこと>
>>個人001 : aaa abc 25
>>個人002 : bbb あああ 75
>>個人003 : ccc 哦哦哦 66
>
> 空白埋めで揃えるというアプローチがそもそも間違っているので、
> 表っぽくしたいならDataGridViewか、弁士さんの別解にあるListViewでも使った方がいいと思います。
>
>
> Protected Overrides Sub OnLoad(e As EventArgs)
> MyBase.OnLoad(e)
>
> 'DataGridView設定(ListBox風)
> DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
> 'DataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None ←セル境界線が要らないなら設定
> DataGridView1.ColumnHeadersVisible = False
> DataGridView1.RowHeadersVisible = False
> DataGridView1.AllowUserToResizeColumns = False
> DataGridView1.AllowUserToResizeRows = False
> DataGridView1.AllowUserToAddRows = False
> DataGridView1.ReadOnly = True
> DataGridView1.MultiSelect = False '複数行選択したいならTrue
>
> 'DataGridView行を作る
> DataGridView1.Columns.AddRange({
> New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col1", .Width = 50},
> New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col2", .Width = 50},
> New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col3", .Width = 50},
> New DataGridViewTextBoxColumn() With {.DataPropertyName = "Col4", .Width = 50}
> })
>
> 'DataTableを作成し、DataGridViewに設定
> Dim dt As New DataTable
> dt.Columns.Add("Col1")
> dt.Columns.Add("Col2")
> dt.Columns.Add("Col3")
> dt.Columns.Add("Col4")
> dt.Rows.Add({"個人001", "aaa", "abc", "25"})
> dt.Rows.Add({"個人002", "bbb", "あああ", "75"})
> dt.Rows.Add({"個人003", "ccc", "哦哦哦", "66"})
> DataGridView1.DataSource = dt
>
> End Sub
>
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -