簡體   English   中英

自動調整Excel互操作對象中合並行中的文本。 C#

[英]Autofit text in merged rows in Excel interop objects. C#

我有一種在excel中寫數據的方法,但是有些部分包含很多文本,並且該方法將文本包裝到列中,但是我無法在行中這樣做,因為它們被合並了。 所以我得到這樣的事情:

在此處輸入圖片說明

我需要像這樣獲取它:

在此處輸入圖片說明

有沒有辦法通過代碼做到這一點? 使用互操作對象。 謝謝你的幫助。

我不知道這是否正確,但是我提出了以下解決方案。 這個想法如下:

  1. 記住行數
  2. 計算合並區域中所有行的總高度
  3. 根據總高度計算每一行的百分比
  4. 解除單元格
  5. 自動調整行
  6. 記住第一行(即數據行)的高度- 高度
  7. 主要 :將百分比(第3階段)應用於身高
  8. 合並單元格回來(在階段1的行數幫助下)

如您所見,此方法是通用的-即,它將對合並區域中的任何行計數起作用,並且將根據新高度遵循每行的先前比率。 您可以使用代碼下載示例工作簿

VBA

Sub Test()
    Call AutoFitMergedCells(Range("D11"))
End Sub

Sub AutoFitMergedCells(cell As Range)

    Dim dOldHeight#, dNewHeight#, dPercent#, arow, addr, rows_count
    Dim dicCells As New Dictionary, dicHeights As New Dictionary

    '// turn off flickering
    Application.ScreenUpdating = False

    With cell

        '// remember rows count for merging cells back
        rows_count = .MergeArea.Count

        '// every dictionary entry holds following info:
        '// 1) original height of all rows in merged cells
        '// 2) percentage of row's height to height of all rows in merged area
        For Each arow In .MergeArea.Rows
            With arow.Cells(1)
                Set dicHeights = New Dictionary
                dicHeights("height") = .RowHeight
                dicHeights("percent") = 0
                dicCells.Add Key:=.Address(0, 0), Item:=dicHeights
            End With
        Next

        '// total height of all rows
        For Each addr In dicCells.Keys()
            dOldHeight = dOldHeight + dicCells(addr)("height")
        Next

        '// update the percentage of every row
        For Each addr In dicCells.Keys()
            dicCells(addr)("percent") = dicCells(addr)("height") / dOldHeight
        Next

        .UnMerge
        .EntireRow.AutoFit
        '// remember new height
        dNewHeight = .RowHeight

        '// this applies percentage of previous row's height to new height
        For Each addr In dicCells.Keys()
            Range(addr).EntireRow.RowHeight = dicCells(addr)("percent") * dNewHeight
        Next

        '// merge back
        .Resize(rows_count).Merge

    End With

    Application.ScreenUpdating = True

End Sub

UPDATE

C#

using System.Diagnostics;
using Excel = Microsoft.Office.Interop.Excel;

private void ProcessMergedCells()
{

    var xlApp = new Excel.Application { Visible = false, ScreenUpdating = false };
    // get Excel process in order to kill it after the work is done
    var xlHandle = new IntPtr(xlApp.Hwnd);
    var xlProc = Process
                 .GetProcesses()
                 .First(p => p.MainWindowHandle == xlHandle);
    var book = xlApp.Workbooks.Open(@"C:\AutoFitMergedCells.xlsm");
    var sheet = book.Sheets[1] as Excel.Worksheet;

    // obtain merged cells any way you like
    // here I just populate array with arbitrary cells
    var merged_ranges = new Excel.Range[]
    {
        sheet.Range["D11"],
        sheet.Range["D13"]
    };

    // process merged cells
    foreach(var merged_range in merged_ranges)
    {
        AutoFitMergedCells(merged_range);
    }

    // quit with saving
    book.Close(SaveChanges: true);
    xlApp.Quit();

    // clean up
    GC.Collect();
    GC.WaitForFullGCComplete();

    // kill Excel for sure
    xlProc.Kill();

}

private void AutoFitMergedCells(Excel.Range merged_range)
{

    double dOldHeight = 0d, dNewHeight = 0d;
    var dicCells = new Dictionary<string, Dictionary<string, double>>();

    // remember rows count for merging cells back
    int rows_count = merged_range.MergeArea.Count;

    // every dictionary entry holds following info:
    // 1) original height of all rows in merged cells
    // 2) percentage of row's height to height of all rows in merged area
    foreach (Excel.Range the_row in merged_range.MergeArea.Rows)
    {
        // we need only top-left cell
        var first_cell = the_row.Cells[1];
        var dicHeights = new Dictionary<string, double>
        {
            ["height"] = first_cell.RowHeight,
            ["percent"] = 0d
        };
        dicCells[first_cell.Address[0, 0]] = dicHeights;
    }

    // total height of all rows
    foreach (string addr in dicCells.Keys)
        dOldHeight += dicCells[addr]["height"];

    // update the percentage of every row
    foreach (string addr in dicCells.Keys)
        dicCells[addr]["percent"] = dicCells[addr]["height"] / dOldHeight;

    // unmerge range and autofit
    merged_range.UnMerge();
    merged_range.EntireRow.AutoFit();

    // remember new height
    dNewHeight = merged_range.RowHeight;

    // this applies percentage of previous row's height to new height
    var sheet = merged_range.Parent;
    foreach (string addr in dicCells.Keys)
        sheet.Range[addr].EntireRow.RowHeight = dicCells[addr]["percent"] * dNewHeight;

    // merge back
    merged_range.Resize[rows_count].Merge();

}

我不記得我在哪里看到過這個東西,但是我曾經看到一個黑客來實現這一目標。 簡而言之,您可以從合並的單元格中獲取有問題的文本,將其粘貼到同一列中的非合並單元格中,然后對該單元格進行自動擬合以查看其高度。 然后,將安全單元的高度設為該高度,然后將其手動設置為每個合並的行,除以合並的行總數。

這很丑陋,但確實有效。 在您的示例中,如果始終為兩行,則這將變得非常容易,因為您始終可以將其除以2,並將行數增加2。 如果不是,則只需要考慮這一點。假設C1是我們的“安全單元”,它將看起來像這樣:

Excel.Range testCell = ws.Cells[1, 3];
testCell.WrapText = true;

for (int row = 11; row < ws.UsedRange.Rows.Count; row += 2)
{
    testCell.Value2 = ws.Cells[row, 4].Value2;
    testCell.Rows.AutoFit();
    ws.Range[string.Format("{0}:{1}", row, row + 1)].RowHeight = testCell.RowHeight / 2;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM