How do I remove a single cell from a word table using Novacode DocX?
I have tried:
table.Rows[0].Cells.RemoveAt(2);
and
Cell c = table.Rows[0].Cells[2];
table.Rows[0].Cells.Remove(c);
and
table.Rows[0].Cells.RemoveRange(2,4);
None of them remove any cells.
I have been working with Novacode DocX very recently. Something I have realized is that a lot of the methods classes have are inherited and are not overridden. An example is cell inherits Remove() from container and is never overridden to do what you would expect it to do.
sorcecode for Novacode.Table
What you can do to try and get around this is to hide the cell/cells, since I am assuming you are not removing an entire row or column.
Novacode.Table table = document.Tables[0]
Novacode.Row row = table.Rows[0]; //int of row that contains cell/cells to remove
int first_cell = 0; //beginning cell of range
int last_cell = 1; //last cell of range
for(int i = first_cell; i < last_cell + 1; i++)
{
foreach (var paragraph in row.Cells[i].Paragraphs)
{
paragraph.Remove(false);
}
}
row.MergeCells(first_cell, last_cell);
Novacode.Cell cell = row.Cells[first_cell];
Novacode.Border border = new Border();
border.Tcbs = Novacode.BorderStyle.Tcbs_none;
cell.SetBorder(Novacode.TableCellBorderType.Right, border);
cell.SetBorder(Novacode.TableCellBorderType.Left, border);
cell.SetBorder(Novacode.TableCellBorderType.Top, border);
cell.SetBorder(Novacode.TableCellBorderType.Bottom, border);
This code would remove text and merge the first two cells of your first table and make there borders invisible. So this would turn the area you want deleted into one invisible blank cell, assuming you are using Paragraphs of text in the Cell.
You may have to save the table back to the document.
Try
appending the table to the end of the document. if that's missing the cells
Remove and replace the table in the document.
You have to clear the child XML from the Cell Element yourself, as it is not correctly handled by the NovaCode DocX Api:
table.Rows.Last().Cells.Last().Xml.RemoveAll();
table.Rows.Last().Cells.Last().InsertParagraph();
Note that the InsertParagraph in the end is necessary as Cells cannot be empty.
In the Table class you can use the methods
MergeCells(int, int)
and
MergeCellsInColumn(int, int, int)
to 'remove' cells.
See: https://docx.codeplex.com/SourceControl/latest#DocX/Table.cs
Related
I'm inserting a table to a word document where the document contains nothing except for a header:
using (var doc = WordprocessingDocument.Open(targetfile, true))
{
var body = doc.MainDocumentPart.Document.Body;
var table = new Table();
foreach (var package in consignment.Packages)
{
// Build the table rows here
}
doc.MainDocumentPart.Document.Append(table);
doc.MainDocumentPart.Document.Save();
doc.Save();
}
Its working well, but when I open the document I can see there is a carriage return at the beginning of the document, so I have to delete that to remove the space:
The annoying space is highlighted in yellow, with the bottom of the header above and my table below.
How can I get OpenXML to not do this? I.e. insert the table right at the top of the document, not after a carriage return
Note that the carriage return is not there in the template docx
The reason the table is not at the top of the document is because: 1) a document always contains, at a minimum, one paragraph and 2) the table is being appended to the document (meaning "at the end").
Instead, insert the table before the first paragraph, something like this:
var body = doc.MainDocumentPart.Document.Body;
var table = new Table();
foreach (var package in consignment.Packages)
{
// Build the table rows here
}
Paragraph firstPara = doc.Body.Descendants<Paragraph>().First();
body.InsertBefore(table, firstPara);
Note that there will be a paragraph mark following the table - this is required by Word in order to store information about the table. (Mainly, it's location on the page.)
I want to put an image inside a tables cell in MigraDoc, but I end up with image stretching the whole row. The part of the simpilfied code looks like so:
table = sec.AddTable();
table.Borders.Width = 0.1; //only for visualization
column = table.AddColumn("6cm");
column = table.AddColumn("7.5cm");
column = table.AddColumn("2.5cm");
row = table.AddRow();
row[0].AddParagraph("title");
row[1].AddImage("C:\\sample.jpg").Width = "3cm";
row = table.AddRow();
row[0].AddParagraph(" - some text");
row = table.AddRow();
row[0].AddParagraph(" - some text");
row = table.AddRow();
row[0].AddParagraph(" - some text");
row = table.AddRow();
row[2].AddParagraph("0.00$");
First image below shows the result and the second one - the desired effect.
When you set .WrapFormat.Style = WrapStyle.Through for the image then the image will be ignored by the layouter and the height of the row will not be adapted to the image.
If the table has borders then you may have to add the image after the table to have it drawn on top of the table.
A simple alternative could be using .MergeDown for the table cell with the image. This is like RowSpan in HTML. In this case the table will grow to fit the image, so you cannot get the effect of the second image (image extends below the table).
This avoids the complications that come with WrapStyle.Through if you have to deal with many different image sizes and should give you clean pagebreaks if the table should not fit a single page.
The Invoice sample does not use images in tables, but it used MergeDown:
http://pdfsharp.net/wiki/Invoice-sample.ashx
I am working with DocX, a library for creating Microsoft .docx files from C#. https://docx.codeplex.com/
I need to merge some tables inside same row. I already figured out how to merge them inside a column.
var doc = DocX.Load(fileName);
Table t3 = doc.AddTable(39, 11);
t3.Alignment = Alignment.center;
t3.Design = TableDesign.TableGrid;
t3.MergeCellsInColumn(0, 0, 9);
doc.InsertTable(t3);
Row row = table.InsertRow();
if use: row.MergeCells(0, 3);
It merge both column and row
So, can use to remove rows empty
row.Cells[0].RemoveParagraphAt(3);
row.Cells[0].RemoveParagraphAt(2);
row.Cells[0].RemoveParagraphAt(1);
and use : table.MergeCellsInColumn(2, 1, 1);
Only merge rows in a column
To merge cells inside a row you need to define the row first. A bitt different than in Colums where you define the colum inside the function.
t2.Rows[0].MergeCells(1, 2);
Set font use Docx.dll:
FontFamily font = new FontFamily("Times New Roman");
Row row = table.InsertRow();
row.Paragraphs[0].Font(font).FontSize(13);
I want to introduce a graphical separation between group of rows in a DataGridView.
Which are the options I have:
- Should I introduce an empty row?
- Should I work with borders and/or the paint methods ?
This increases the lower border of the row at specified [Index]:
DataGridViewRow row = dataGridView1.Rows[Index];
row.DividerHeight = 1;
Note that DividerHeigth uses the space of the row, so if you set it to 10 it can cover half row (for me, 1 is enough).
There is also DividerWidth property to separate groups of columns.
grid.Rows.Insert(index, 1);
var addedRow = grid.Rows[index];
This inserts 1 empty templated row at 'index'.
With the Rows.Add() method you add a new row, you can obtain a reference to it by using:
var newRow = dg.Rows[dg.Rows.Add()];
So you can manipulate your new row after, example:
newRow.Cells["myColumn"].Value = "asd";
DataGridViewRow DGVR= (DataGridViewRow)yourDataGridView.Rows[0].Clone();
DGVR.Cells[0].Value = "XYZ";
DGVR.Cells[1].Value = 50.2;
yourDataGridView.Rows.Add(DGVR);
Do you know an equivalent to VBA code:
Range(Selection, Selection.End(xlToRight)).Select
In Aspose.Cells. It seems that its only possible to select the last cell in the entire row:
public Aspose.Cells.Cell EndCellInRow ( Int32 rowIndex )
Or the last cell on the right within a range:
public Aspose.Cells.Cell EndCellInRow ( Int32 startRow, Int32 endRow, Int32 startColumn, Int32 endColumn )
but then you must know more or less how big your table is going to be.
I found this from 2009: http://www.aspose.com/community/forums/permalink/196519/196405/showthread.aspx but that will not resolve my problem as I may have many tables in a sheet both horizontally and vertiacally. And I can't predict where they are going to be.
Edit1:
Sorry if this is dumb question, but ctrl+shift+arrow is such a common operation that I can't believe it would be not implemented so I'm making sure I really have to re-invent the wheel.
Aspose.Cells provides the list of tables in a worksheet using property named 'Worksheet.ListObjects'. 'ListObjects' is a colloection of 'ListObject' type which represents a Table in an excel sheet. That means if one has more than one Tables in a worksheet, the ListObjects collection will give access to every table in the worksheet very conveniently. Each 'ListObject' in turn contains a property named 'DataRange' which specifies all the cells inside a Table. For the sake of convenience DataRange can be used for following operations on a Table:
To apply styles/formatting on the cells in Table
To get the data values
Merge or move the cells in Range
Export contents
To get enumerator to traverse through Table cells
To make selection of cells from DataRange, you can traverse using DataRange to get all the cells in a Row (This could also be done for a column)
Applying any operation on Table cells like after selecting cells using Ctrl+Shift+Arrow, could be performed using a workbook object as follows:
Workbook workbook = new Workbook(new FileStream("book1.xls", FileMode.Open));
if (workbook.Worksheets[0].ListObjects.Count > 0)
{
foreach (ListObject table in workbook.Worksheets[0].ListObjects)
{
Style st = new Style();
st.BackgroundColor = System.Drawing.Color.Aqua;
st.ForegroundColor = System.Drawing.Color.Black;
st.Font.Name = "Agency FB";
st.Font.Size = 16;
st.Font.Color = System.Drawing.Color.DarkRed;
StyleFlag stFlag = new StyleFlag();
stFlag.All = true;
table.DataRange.ApplyStyle(st, stFlag);
}
}
workbook.Save("output.xls");
There is also some worthy information available in Aspose docs about Table styles and applying formatting on a ListObject. For getting last Table cell in a certain row or column, I am sure this will help:
int iFirstRowIndex = table.DataRange.FirstRow;
int iFirstColumnIndex = table.DataRange.FirstColumn;
int iLastRowIndex = table.DataRange.RowCount + iFirstRowIndex;
int iLastColumnIndex = table.DataRange.ColumnCount + iFirstColumnIndex;
for (int rowIndex = 0; rowIndex < table.DataRange.RowCount; rowIndex++)
{
//Get last cell in every row of table
Cell cell = worksheet.Cells.EndCellInColumn(rowIndex + iFirstRowIndex, rowIndex + iFirstRowIndex, (short)iFirstColumnIndex, (short)(iLastColumnIndex - 1));
//display cell value
System.Console.WriteLine(cell.Value);
}