Автоподбор текста в объединенных строках в объектах взаимодействия Excel.C # - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть метод, который записывает данные в Excel, но есть части, которые содержат много текста, и метод переносит текст в столбец, но я не могу сделать это в строках, потому что они объединены.Итак, я получаю что-то вроде этого:

enter image description here

И мне нужно получить это так:

enter image description here

Есть ли способ сделать это по коду?Использование Interop Objects.Спасибо за любую помощь.

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Я не знаю, правильно ли это или нет, но я нашел следующее решение.Идея заключается в следующем:

  1. запомнить количество строк
  2. вычислить общую высоту всех строк в объединенной области
  3. вычислить процент каждой строки в соответствии с общей высотой
  4. unmerge ячейки
  5. строки автоподбора
  6. запомнить высоту первой строки (т.е. строки данных) - a new высота
  7. main : применить процент (на этапе 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

ОБНОВЛЕНИЕ

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();

}
0 голосов
/ 20 декабря 2018

Я не помню, где я видел это, но однажды я увидел хак для достижения этой цели.Короче говоря, вы берете соответствующий текст из объединенной ячейки, вставляете его в не объединенную ячейку в том же столбце и выполняете автоподбор в этой одной ячейке, чтобы увидеть, насколько высоким он должен быть.Затем вы берете эту высоту безопасной ячейки и вручную устанавливаете ее для каждой объединенной строки, деля на общее количество объединенных строк.

Это некрасиво, но работает.В вашем примере, если это всегда две строки, это делает это намного проще, потому что вы всегда можете разделить на два и увеличить количество строк на два.Если нет, вам просто нужно учесть это. Предполагая, что 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...