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

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

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

Re[6]: ClosedXMLで行高さを自動調整する方法


(過去ログ 179 を表示中)

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

■102454 / inTopicNo.1)  ClosedXMLで行高さを自動調整する方法
  
□投稿者/ 河童 (1回)-(2023/10/04(Wed) 22:24:22)

分類:[C#] 

Windows 11 Home
C#
VS2019 .NET Framework 4.7.2
ClosedXML 0.87.0.0

Windowsフォームアプリを作成しています。
ClosedXMLで行の高さを自動調整する方法を教えてください。

値をセルに代入して、セルを結合しています。
値は、改行を含む文字列(日本語の文章)です。
セルの書式設定で折り返して表示を選択。

文字列が長くなると複数行になって表示され、
行数に合わせて行の高さを自動調整したいと思っています。
行を指定して、AdjustToContents で実行しているのですが、
行の高さが変わりません。

行の高さを自動調整する方法を教えてください。
よろしくお願いいたします。


// ClosedXMLを使ってxlsxファイルを作成する
xlPath = Application.StartupPath + "\\Excel\\Syukei.xlsx";
            
// エクセルオープン
ClosedXML.Excel.XLWorkbook workbook = null;
workbook = new XLWorkbook(xlPath);

IXLWorksheet tmpWS = workbook.Worksheet("sheet");

tmpWS.Cell(CopyRow, tCol3).Value = val;
tmpWS.Range(CopyRow, tCol3, CopyRow , tCol4).Merge();
tmpWS.Row(CopyRow).AdjustToContents();

引用返信 編集キー/
■102455 / inTopicNo.2)  Re[1]: ClosedXMLで行高さを自動調整する方法
□投稿者/ KOZ (412回)-(2023/10/05(Thu) 00:10:55)
No102454 (河童 さん) に返信
> 行を指定して、AdjustToContents で実行しているのですが、
> 行の高さが変わりません。

これだと変わらないですね。なぜだろう。

> 行の高さを自動調整する方法を教えてください。

セルのプロパティ「折り返して全体を表示」にするとうまくいきます。
ただし。結合セルだとうまくいきませんでした。

const string filename = @"Z:\MergedRowHeight.xlsx";

using (var workbook = new XLWorkbook()) {
    var worksheet = workbook.Worksheets.Add("Sheet1");

    var A1 = worksheet.Cell("A1");
    A1.Value = "This is a long text that will be merged across multiple cells.";
    A1.Style.Alignment.SetWrapText(true);

    var A2_A3 = worksheet.Range("A2:A3");
    A2_A3.Merge();
    A2_A3.Value = "This is a long text that will be merged across multiple cells."; ;
    A2_A3.Style.Alignment.SetWrapText(true);
}

A1 は縦にひろがってくれたのですが、A2:A3 のほうはそのままです。
もっとも結合すると、Excel の操作でも広がらないのでどうしようもないかもしれません。
高さを調整しようと思ったのですが、行の高さは 15 のままでした。

保存した後、再オープンしても行の高さは 15 のままです。
ファイル自体には、行の大きさは記録されていないようですが、Excel で
開いて保存したあとで開くと行の高さが 120 に広がっていました。
Excel が開くときに大きさを調整しているようです。

なかなか面倒そう。:(

引用返信 編集キー/
■102456 / inTopicNo.3)  Re[2]: ClosedXMLで行高さを自動調整する方法
□投稿者/ 河童 (2回)-(2023/10/05(Thu) 09:56:12)
No102455 (KOZ さん) に返信
ご回答ありがとうございます。

エクセルのフォーマットで結合セルを利用したいと思っております。
別の方法として、代入する値に改行がいくつ含まれているかを
判定して結合する行数を決めるようにしました。

わからないことがあります。
改行を含まずに長い文章が代入されたときにどのように行数を追加するかです。
全角半角文字があるので1行の文字数を決めるのが難しいです。

改行を含めた文字列に応じて行数を判定する方法があればお教えてください。
よろしくお願いいたします。




// エクセルの行高さは2行分を結合して1行とする
// 行高さの初期値
int TokkiRow = 4;

// 特記欄に表示する値は、改行を含めて自由入力
var val = "おはよう。\r\nこんにちは。\r\nさようなら。\r\nおはよう。";

// 改行の個数
int NewLineCnt = val.Length - val.Replace("\r\n", "").Length;
NewLineCnt = NewLineCnt / 2;

// 改行文字が2つ以上ある場合(3行以降)は、1つにつき行を2行追加する
for (int i = 2; i < NewLineCnt; i++)
{
TokkiRow += 2;
}

//MessageBox.Show(NewLineCnt.ToString());
//MessageBox.Show(val.ToString());
//MessageBox.Show(TokkiRow.ToString());

// セルを結合して行高さを確保
tmpWS.Cell(CopyRow, tCol3).Value = val;
tmpWS.Range(CopyRow, tCol3, CopyRow + TokkiRow, tCol4).Merge();

//tmpWS.Row(CopyRow).AdjustToContents();
引用返信 編集キー/
■102457 / inTopicNo.4)  Re[3]: ClosedXMLで行高さを自動調整する方法
□投稿者/ KOZ (413回)-(2023/10/05(Thu) 10:17:55)
No102456 (河童 さん) に返信
> 改行を含まずに長い文章が代入されたときにどのように行数を追加するかです。
> 全角半角文字があるので1行の文字数を決めるのが難しいです。
>
> 改行を含めた文字列に応じて行数を判定する方法があればお教えてください。

セルの幅やフォントを設定していろいろ試してみるしかないかと。
TextRenderer.MeasureText メソッドの値が目安になるかもしれないですが、やってみないとわかりません。
引用返信 編集キー/
■102458 / inTopicNo.5)  Re[3]: ClosedXMLで行高さを自動調整する方法
□投稿者/ radian (152回)-(2023/10/05(Thu) 13:10:37)
2023/10/05(Thu) 16:28:36 編集(投稿者)

No102456 (河童 さん) に返信
> 改行を含めた文字列に応じて行数を判定する方法があればお教えてください。

そんなことは不可能なので、諦めてサイズを固定するなど他の仕様を考えてください。
行数は表示する拡大率が変わるだけでも変動するので、容易に破綻します。
引用返信 編集キー/
■102459 / inTopicNo.6)  Re[4]: ClosedXMLで行高さを自動調整する方法
□投稿者/ KOZ (414回)-(2023/10/05(Thu) 16:40:09)
2023/10/05(Thu) 17:00:54 編集(投稿者)
No102457 (KOZ) に返信
> セルの幅やフォントを設定していろいろ試してみるしかないかと。
> TextRenderer.MeasureText メソッドの値が目安になるかもしれないですが、やってみないとわかりません。

イケたかも。

using ClosedXML.Excel;
using System;
using System.Drawing;
using System.Windows.Forms;

internal class Program
{
    static void Main(string[] args) {

        const string filename = @"Z:\MergedRowHeight.xlsx";
        const string longText = "This is a long text that will be merged across multiple cells.";

        using (var workbook = new XLWorkbook()) {
            var worksheet = workbook.Worksheets.Add("Sheet1");
            var A1 = worksheet.Cell("A1");
            A1.Value = longText;
            A1.Style.Alignment.SetWrapText(true);

            var A2_A3 = worksheet.Range("A2:A3");
            A2_A3.Merge();
            A2_A3.Value = longText;
            A2_A3.Style.Alignment.Vertical = XLAlignmentVerticalValues.Top;
            A2_A3.Style.Alignment.SetWrapText(true);
            worksheet.Row(2).Height = A2_A3.GetHeight(longText)
                                    - worksheet.Row(3).Height;

            workbook.SaveAs(filename);
        }
    }
}

internal static class ExcelUtl
{
    const int DPI = 96;
    const double PointsPerInch = 72.0;
    const double PixelsPerChar = 7;

    public static double GetHeight(this IXLRange range, string text) {
        return range.Cell(1, 1).GetHeight(text);
    }

    public static double GetHeight(this IXLCell cell, string text) {
        var font = CreateFont(cell.Style.Font);
        var width = (int)(PixelsPerChar * cell.WorksheetColumn().Width);
        using (var g = Graphics.FromHwnd(IntPtr.Zero)) {
            var size = new Size(width, short.MaxValue);
            TextFormatFlags flags =
                TextFormatFlags.Left | TextFormatFlags.Top | TextFormatFlags.WordBreak;
            size = TextRenderer.MeasureText(g, text, font, size, flags);
            return PixelsToPoints(size.Height);
        }
    }

    public static int PointsToPixels(double points) {
        return (int)(points * DPI / PointsPerInch);
    }

    public static double PixelsToPoints(int pixels) {
        return (int)(pixels * PointsPerInch / DPI);
    }

    public static Font CreateFont(IXLFont font) {
        FontStyle style = FontStyle.Regular;
        if (font.Bold) { style |= FontStyle.Bold; }
        if (font.Italic) { style |= FontStyle.Italic; }
        if (font.Underline != XLFontUnderlineValues.None) { style |= FontStyle.Underline; }
        if (font.Strikethrough) { style |= FontStyle.Strikeout; }
        return new Font(font.FontName,
                            (float)font.FontSize, style, GraphicsUnit.Point);
    }
}

まぁ試してみてダメだったら調整してください。

引用返信 編集キー/
■102460 / inTopicNo.7)  Re[4]: ClosedXMLで行高さを自動調整する方法
□投稿者/ 河童 (3回)-(2023/10/05(Thu) 17:06:00)
KOZ 様、ありがとうございます。
試してみます。
引用返信 編集キー/
■102461 / inTopicNo.8)  Re[5]: ClosedXMLで行高さを自動調整する方法
□投稿者/ KOZ (415回)-(2023/10/05(Thu) 18:05:23)
2023/10/05(Thu) 18:13:22 編集(投稿者)

No102460 (河童 さん) に返信
> 試してみます。

日本語を表示すると、ちょっと短くなりますね。
でもフォントを日本語のグリフがあるものにすれば大丈夫です。

workbook.Style.Font.FontName = "MS UI Gothic";

TextRenderer.MeasureText はフォントリンクが機能してないのかな・・・
引用返信 編集キー/
■102462 / inTopicNo.9)  Re[5]: ClosedXMLで行高さを自動調整する方法
□投稿者/ KOZ (416回)-(2023/10/05(Thu) 22:52:37)
2023/10/07(Sat) 11:36:35 編集(投稿者)

No102459 (KOZ) に返信

見直してみて気になった点
・Font オブジェクトを Dispose していない
・TextFormatFlags は Style やセルの属性を見て調整したほうがよさそう
・名前は GetHeight より GetTextHeight とかにしたほうがよかったかも
 MeasureText として Size を返したほうがよかっただろうか(わりとどうでもいい)
・おそらく横幅は近いところまで持っていけますが、縦幅は無理っぽいので1行になる高さ("A") と2行になる高さ("A\nB") を調べて行の高さと余白をもとめ、書き込む文字列の高さから行数をもとめるといいかも。
引用返信 編集キー/
■102463 / inTopicNo.10)  Re[6]: ClosedXMLで行高さを自動調整する方法
□投稿者/ 河童 (4回)-(2023/10/09(Mon) 02:27:16)
No102461 (KOZ さん) に返信
なかなか難しいですね。
KOZ 様、いろいろありがとうございました。

今回の行高さは、きっちりと調整する必要はないので、
1行の文字数を固定にして、行数を追加することにします。
文字数は半角全角を問わずだいだいの文字数を設定します。

行数がすくなく印刷したときに表示が切れるよりかは、
多めに行数をとって余白にした方がいいかなと考えます。

解決済み
引用返信 編集キー/
■102464 / inTopicNo.11)  Re[5]: ClosedXMLで行高さを自動調整する方法
□投稿者/ kiku (382回)-(2023/10/10(Tue) 13:37:16)
No102460 (河童 さん) に返信
> KOZ 様、ありがとうございます。
> 試してみます。

試してみた結果を記載するのが
KOZさんに対しての感謝ではないかと思いますが。。。
回答者の労力を考えて欲しいとは思います。
解決済み
引用返信 編集キー/
■102476 / inTopicNo.12)  Re[6]: ClosedXMLで行高さを自動調整する方法
□投稿者/ KOZ (419回)-(2023/10/11(Wed) 16:00:29)
2023/10/11(Wed) 18:11:24 編集(投稿者)

No102464 (kiku さん) に返信

kiku さん、なんだかありがとうございます。

> 試してみた結果を記載するのが
> KOZさんに対しての感謝ではないかと思いますが。。。
> 回答者の労力を考えて欲しいとは思います。

これについては、「イケたかも」ってのは、たまたまだったようで、検証して予想がついてました。
折り返しの位置は高い精度で再現できましたが、行の高さは無理かなと。
(GDIには行の高さを変更する手段がないのです。Excel はどうやってるんだろう)

なので ■No102462 で行数から求めるといいかもという発言をしています。

河童さんがうまいこと調整してくれるかなーと期待してました。

解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -