openxml - вставка строки, перемещение других - PullRequest
5 голосов
/ 24 июня 2010

Я использую openxml для создания отчета о Excel. Openxml работает с файлом Excel шаблона, используя именованные диапазоны.

Клиенту требуется строка итогов в конце списка строк. Звучит как разумная просьба !!

Однако таблица данных, которую я возвращаю из базы данных, может содержать любое количество строк. Используя строки шаблона и «InsertBeforeSelf», моя строка итогов переопределяется.

Мой вопрос, используя openxml, как я могу вставить строки в электронную таблицу, заставляя итоговую строку перемещаться вниз при каждой вставке строки?

С уважением ...

Ответы [ 3 ]

7 голосов
/ 14 июля 2010

Предполагая, что вы используете SDK 2.0, я сделал нечто похожее, используя эту функцию:

private static Row CreateRow(Row refRow, SheetData sheetData)
    {
        uint rowIndex = refRow.RowIndex.Value;
        uint newRowIndex;
        var newRow = (Row)refRow.Clone();

        /*IEnumerable<Row> rows = sheetData.Descendants<Row>().Where(r => r.RowIndex.Value >= rowIndex);
        foreach (Row row in rows)
        {
            newRowIndex = System.Convert.ToUInt32(row.RowIndex.Value + 1);

            foreach (Cell cell in row.Elements<Cell>())
            {
                string cellReference = cell.CellReference.Value;
                cell.CellReference = new StringValue(cellReference.Replace(row.RowIndex.Value.ToString(), newRowIndex.ToString()));
            }

            row.RowIndex = new UInt32Value(newRowIndex);
        }*/

        sheetData.InsertBefore(newRow, refRow);
        return newRow;
    }

Я не уверен, как вы делали это с InsertBeforeSelf раньше, так что, возможно, это не так уж много улучшений, но это сработало для меня. Я думал, что вы можете просто использовать вашу итоговую строку в качестве контрольной строки. (Закомментированная часть предназначена для того, чтобы после вашей ссылочной строки у вас были строки, которые вы хотели сохранить. Я внес некоторые изменения, но в основном это происходит из этого потока: http://social.msdn.microsoft.com/Forums/en-US/oxmlsdk/thread/65c9ca1c-25d4-482d-8eb3-91a3512bb0ac)

Поскольку он возвращает новую строку, вы можете затем использовать этот объект для редактирования значений ячеек с данными из базы данных. Надеюсь, это хоть как-то поможет любому, кто пытается это сделать ...

2 голосов
/ 12 января 2011

[Может кто-то с большим количеством очков, пожалуйста, поместите этот текст в качестве комментария к ответу M_R_H.]

Решение, которое дал M_R_H, помогло мне, но внесло новую ошибку в проблему. Если вы используете данный метод CreateRow «как есть», если какая-либо из строк, для которых выполняется перемещение / повторная ссылка, имеет формулы, CalcChain.xml (в пакете) будет поврежден. Я добавил следующий код в предлагаемое решение CreateRow. Это все еще не решает проблему, потому что, я думаю, этот код только исправляет скопированную в данный момент ссылку на строку:

if (cell.CellFormula != null) {
     string cellFormula = cell.CellFormula.Text;
     cell.CellFormula = new CellFormula(cellFormula.Replace(row.RowIndex.Value.ToString(), newRowIndex.ToString()));
}

Как правильно исправить / обновить CalcChain.xml?

PS: SheetData можно получить из вашего рабочего листа как:

worksheet.GetFirstChild<SheetData>();
0 голосов
/ 17 января 2019

Вы должны зациклить все строки и ячейки под вставленной строкой, изменить ее индекс строки и ссылку на ячейку. Я полагаю, что OpenXml не настолько умен, чтобы помочь вам автоматически менять индекс.

static void InsertRow(string sheetName, WorkbookPart wbPart, uint rowIndex)
    {
        Sheet sheet = wbPart.Workbook.Descendants<Sheet>().Where((s) => s.Name == sheetName).FirstOrDefault();

        if (sheet != null)
        {
            Worksheet ws = ((WorksheetPart)(wbPart.GetPartById(sheet.Id))).Worksheet;
            SheetData sheetData = ws.WorksheetPart.Worksheet.GetFirstChild<SheetData>();
            Row refRow = GetRow(sheetData, rowIndex);
            ++rowIndex;

            Cell cell1 = new Cell() { CellReference = "A" + rowIndex };
            CellValue cellValue1 = new CellValue();
            cellValue1.Text = "";
            cell1.Append(cellValue1);
            Row newRow = new Row()
            {
                RowIndex = rowIndex
            };
            newRow.Append(cell1);
            for (int i = (int)rowIndex; i <= sheetData.Elements<Row>().Count(); i++)
            {
                var row = sheetData.Elements<Row>().Where(r => r.RowIndex.Value == i).FirstOrDefault();
                row.RowIndex++;
                foreach (Cell c in row.Elements<Cell>())
                {
                    string refer = c.CellReference.Value;
                    int num = Convert.ToInt32(Regex.Replace(refer, @"[^\d]*", ""));
                    num++;
                    string letters = Regex.Replace(refer, @"[^A-Z]*", "");
                    c.CellReference.Value = letters + num;
                }
            }
            sheetData.InsertAfter(newRow, refRow);
            //ws.Save();
        }
    }

    static Row GetRow(SheetData wsData, UInt32 rowIndex)
    {
        var row = wsData.Elements<Row>().
        Where(r => r.RowIndex.Value == rowIndex).FirstOrDefault();
        if (row == null)
        {
            row = new Row();
            row.RowIndex = rowIndex;
            wsData.Append(row);
        }
        return row;
    }

Приведенное выше решение получено из: Как вставить строку в существующий шаблон в открытом XML Существует четкое объяснение, которое может вам очень помочь.

...