I'm splitting a cell into two columns:
table.Cell(1,1).Split(1,2);
How can I access the two new cells?
As with many things in Word, the trick to getting "pointers" to objects is to work with Ranges.
In this case, if a Range to the original cell is instantiated it's possible to refer back to it. After the split it will be in the first cell. From it, it's possible to get both the first and second cells (and, indeed, anything else in the table).
For example
Word.Table tbl = document.Tables[1];
Word.Cell cel = tbl.Cell(1, 1);
Word.Range rng = cel.Range;
cel.Split(1, 2);
//At this point, rng is at the start of the first (left-most) cell of the two
//using new objects for the split cells
Word.Cell newCel1 = rng.Cells[1];
Word.Cell newCel2 = rng.Next(wdCell, 1).Cells[1];
newCel1.Range.Text = "1";
newCel2.Range.Text = "2";
//Alternative: using the original cell, plus a new object for the split cell
//Word.Cell newCel2 = rng.Next(Word.WdUnits.wdCell, 1).Cells[1];
//cel.Range.Text = "1";
//newCel2.Range.Text = "2";
Related
enter image description here
Here, there are four cells(A1,B1,C1,D1) have been merged, I would like to get the editable cell address(A1).
According to Excel A1 Cell able to edit, others not editable.
I could able to get merged cells count as 4 using below code.
Also I can get whether cell has been merged or not.
But not able to get the address of editable cell(A1) in merged cells.
Microsoft.Office.Interop.Excel.Application appl = null;
appl = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook wbk;
wbk = appl.Workbooks.Open("C:\\Users\\test\\Desktop\\test.xlsx");
Worksheet sheet = wbk.Worksheets.get_Item(1);
Range range = sheet.Cells[1, 2]; //B1 Cell
var a = range.Cells.MergeArea.Count; // can be able to get merged count cells
string b = range.Address;
**int ab = range.Cells.Areas.Count;**
Range ac = range.Cells.Areas.get_Item(1);
for (int i = 1; i <= 4; i++)
{
**if (sheet.Cells[1, i].Mergecells)** //merged cell
{
MessageBox.Show("Merged");
}
else //Unmerged cell
{
MessageBox.Show("UnMerged Cells");
}
}
wbk.Save();
wbk.Close(false);
appl.Quit();
The MergeArea property of a Range is again a Range. If you have a cell, just use something like the following to get the first (=top left) cell of the merged area (untested in C# as I don't have it available, but works in VBA and should also work for C#):
Range range = sheet.Cells[1, 2];
Range firstCell = range.MergeArea.Cells[1, 1];
This works even if a cell is not merged, MergeArea is always set, so on an unmerged cell range and firstCell would point to the same cell.
If I correctly understood your real need, please try the next approach. It is based on the fact that a merged area keeps the value in its first cell:
'your existing code...
if (sheet.Cells[1, i].Mergecells) //merged cell
{
MessageBox.Show(sheet.Cells[1, i].MergeArea.cells[1, 1].Value);
}
else //Unmerged cell
{
MessageBox.Show(sheet.Cells[1, i].Value);
}
'your existing code...
Here is the solution
string mergedCellsAddress = mergedRange.Address;
string[] firstMergedCell = mergedCellsAddress.Split(':');
string firstCell = firstMergedCell.GetValue(0).ToString().Replace("$", "");
I have an Excel worksheet with some data. I also have a List of the column headers of the worksheet. The headers in the list are in a different order than the headers in the worksheet, and I need to reorder the Excel worksheet's columns to be the same order as the list.
List<string> dataset1Variables = new List<string>() { "Variable1", "Variable2", "Variable3", "Variable4" };
The headers of my Excel sheet may look like this:
Variable 3 | Variable 1 | Variable 4 | Variable 2
I have come across this code to shift columns but this is only for moving 1 column to a specific location. The list might be completely mixed up so I would need to shift many columns.
Excel.Range copyRange = xlWs.Range["C:C"];
Excel.Range insertRange = xlWs.Range["A:A"];
insertRange.Insert(Excel.XlInsertShiftDirection.xlShiftToRight,
copyRange.Cut());
What would be the best approach for doing this? Preferably using Interop.
If you have an empty row right above your worksheet with data, you can add matching formula right above headers. In below assuming your list is on Sheet2 range B2:B5 and your data headers start on Sheet1 range A2:D2
Excel.Workbook myBook = xlApp.Workbooks.Open(#"path\excel.xlsx");
Excel.Worksheet ws = myBook.Worksheets[1];
// You can use all dynamic ranges instead
// Excel.Range xlRng = ws.Range[ws.Cells[yourRow, firsColumn], ws.Cells[yourRow, lastColumn]];
Excel.Range xlRng = ws.Range[ws.Cells[1, 1], ws.Cells[1, 4]]; // ws.Range["A1:D1"];
xlRng.FormulaR1C1 = "=MATCH(R[-1]C,Sheet2!R2C2:$R5C2,0)";
// Below is how you can get full address for your list if it's in different workbook and replace Sheet2!R2C2:$R5C2 with rangeFullAddress
// string rangeFullAddress = xlRng.Address[true,true,Excel.XlReferenceStyle.xlR1C1,true];
xlRng.Calculate();
xlRng.Value = xlRng.Value;
After this you can just sort your data using Excel Sort by 1st row. After sorting your 1st row it would look like this: 1, 2, 3, 4. Then clear data on 1st row ws.Range["A1:D1"].Clear();.
Your sort key would be Key1: ws.Range["A1:D1"], here is c# sort example using c# to sort a column in excel only change Excel.XlSortOrientation and adjust for your range.
There are other ways to sort but this way you'll keep individual formats, comments of each cell within your data
I missed 1 important detail - that your list is not in Excel sheet, but you can add it to Excel, perhaps in temporary workbook or right on the same sheet:
object [,] columnHeaders = new object[3,0]; // or object[0,3]; if you'd like to add into 1 row
columnHeaders[0, 0] = "Variable1";
columnHeaders[1, 0] = "Variable2";
columnHeaders[2, 0] = "Variable3";
columnHeaders[3, 0] = "Variable4";
xlRng.FormulaR1C1 = columnHeaders; // xlRng would be in the above Sheet2!R2C2:$R5C2
I recently figured out how to write cell values in a range:
Excel.Range rng = (Excel.Range)xlWorkSheet.Range[xlWorkSheet.Cells[1, 1], xlWorkSheet.Cells[10, 10]];
rng.Value = new string[,] { ... };
which speeds up my app enourmous, but I would also like to be able to set a whole range of cell comments! I only found the possibility to make a comment on a range of cells. A single comment. But it does not seem that something for it exists in the api.
You can not set more than one cell comment at once, but you can copy comment from one cell and paste it to multiple cells:
var a1 = xlWorkSheet.Range("A1")
a1.ClearComments(); // just in case
a1.AddComment("some comment");
a1.Copy();
a1.Resize(10, 10).PasteSpecial(Excel.XlPasteType.xlPasteComments);
Given something like
Table table;
Cell cell_1 = table.Cell(2,2);
Cell cell_2 = table.Cell(4,4);
I want to select (or highlight) from cell_1 to cell_2 (like how you would if you were doing it by hand).
I originally thought that doing the following would work:
Selection.MoveRight(wdUnits.wdCell, numCells, WdMovementType.wdExtend)
But according to http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.selection.moveright%28v=office.11%29.aspx under remarks, using wdCells as the Unit will default the WdMovementType to wdMove, and I can't think of a workaround.
Here is a workaround I've found to the problem. It isn't the most efficient way, and it doesn't work if the table has merged cells in it. I've discovered that you can select the range of your start cell, and then expand the end point of the range by moving by in units of cells. By discovering the number of cells between the start and end point of the region you want selected, you can iterate those number of cell steps. Here's the general code for that below:
word.Table table;
word.Cell cellTopLeft; //some cell on table.
word.Cell cellBottomRight; //another cell on table. MUST BE BELOW AND/OR TO THE RIGHT OF cellTopLeft
int cellTopLeftPosition = (cellTopLeft.RowIndex - 1) * table.Columns.Count + cellTopLeft.ColumnIndex;
int cellBottomRightPosition = (cellBottomRight.RowIndex - 1) * table.Columns.Count + cellBottomRight.ColumnIndex;
int stepsToTake = cellBottomRightPosition - cellTopLeftPosition;
if (stepsToTake > 0 &&
cellTopLeft.RowIndex <= cellBottomRight.RowIndex && //enforces bottom right cell is actually below of top left cell
cellTopLeft.ColumnIndex <= cellBottomRight.ColumnIndex) //enforces bottom right cell is actually to the right of top left cell
{
word.Range range = cellTopLeft.Range;
range.MoveEnd(word.WdUnits.wdCell, stepsToTake);
range.Select();
}
A much simpler way to do this is to use the Document.Range method to create a range between the two corners of the rectangle. This works equally well with merged cells.
word.Document document;
word.Cell cellTopLeft;
word.Cell cellBottomRight;
document.Range(cellTopLeft.Range.Start, cellBottomRight.Range.End).Select
Note: One can use the range returned by this expression to manipulate the contents of the table without selecting it, but it doesn't work for merging the cells (in the latter case, use cell.Merge(MergeTo) ).
I'm working with an excel object in c#. I want to auto-fit the columns, but like this: I want the columns' width to be 5 bigger than what the AutoFit method set.
How can I get the width after AutoFit() is used?
How can I make the columns 5 bigger than this width?
If you wish to use the Selection object and have IntelliSense with early binding, you need to cast the Selection object to a Range first:
Excel.Range selectedRange = (Excel.Range)myExcelApp.Selection;
selectedRange.Columns.AutoFit();
foreach (Excel.Range column in selectedRange.Columns)
{
column.ColumnWidth = (double)column.ColumnWidth + 5;
}
-- Mike
Assuming that you are on cell A1 & have long text in it, following code will make the column Autofit and then increase the width by 5 characters.
Selection.Columns.Autofit
Selection.Columns(1).ColumnWidth = Selection.Columns(1).ColumnWidth + 5
Try to loop through your rows to get the text length of it:
var row = 1;
ws.Column(1).AutoFit(ws.Cells[row, 1].Text.Length + 5);
Where ws is your Worksheet:
var pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Plan1")
Try Like this,
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Sheet1");
//Load the datatable into the sheet, starting from cell A1. Print the column names on row 1
ws.Cells["A1"].LoadFromDataTable(data_table, true);
//Set full Sheet Auto Fit
ws.Cells[1, 1, data_table.Rows.Count, data_table.Columns.Count].AutoFitColumns();