Why is my "defined name" (range) value not being set with this Spreadsheet Light code? - excel

I've got this code to apply a "header" (big, top-of-the-sheet "title") to a sheet:
// Initialize
private static SLDocument sl;
. . .
sl = new SLDocument();
// Create a Style
SLStyle styleHeading = sl.CreateStyle();
styleHeading.SetFont(FontSchemeValues.Major, 36);
styleHeading.Font.Italic = true;
styleHeading.Font.FontName = "Candara";
// Create a Defined Name (Range) and give it a value and style
sl.SetDefinedName("UnitName", "Sheet1!$A$1:$A$13");
sl.SetCellValue("UnitName", "Pennsylvania Platypi Presumptuously Parasailing");
sl.SetCellStyle("UnitName", styleHeading);
// Save the sheet
string appDataFolder = HttpContext.Current.Server.MapPath("~/App_Data/");
string spreadsheetLightFilename = "PlatypiTest.xlsx";
string fullspreadsheetLightPath = Path.Combine(appDataFolder, spreadsheetLightFilename);
sl.SaveAs(fullspreadsheetLightPath);
Note: I verified that "Sheet1" was right with this code:
var nameList = sl.GetSheetNames();
string s = nameList[0]; // "s" is "Sheet1"
The file is created and saved, but it is devoid of content; when I open it, cell A1 is highlighted, but is content-free.
Am I missing a vital step, or going about this completely wrong?

What are you doing is logically fine.
This line
sl.SetDefinedName("UnitName", "Sheet1!$A$1:$A$13");
indeed creates a named range. You can see it if you open the resulting file in Excel and look at the cell selector:
or the Name Manager:
The problem is though that Spreadsheet Light has a very basic support for Defined names - basically all you can do is to create a name and use it inside the formulas. All methods that manipulate content expect single cell reference. Btw, all these methods do not throw exception if you don't pass a valid cell reference, but return bool indicating success/failure.
For instance, if you change your code to
bool success1 = sl.SetCellValue("UnitName", "Pennsylvania Platypi Presumptuously Parasailing");
bool success2 = sl.SetCellStyle("UnitName", styleHeading);
you will see that both success variables are false.
Shortly, if you want to bring some content to the Excel file, you should do it cell by cell. It even does not support regular (unnamed) ranges.

Theoretically, at least, you could do it this way:
// from http://stackoverflow.com/questions/36481802/what-is-the-analogue-to-excel-interops-worksheet-usedrange-rows-in-spreadsheet
var stats = sl.GetWorksheetStatistics();
var rowcount = stats.NumberOfRows;
SLStyle entireSheetRangeStyle = sl.CreateStyle();
entireSheetRangeStyle.// (set style vals)
. . .
sl.SetRowStyle(1, rowcount, entireSheetRangeStyle);

Related

Update an Excel style in VBA

My Excel macro reads the answers to a survey from a set of Excel files. The answers of a survey contain a score (from 1 to 4) and a description. The goal is to generate a a matrix. Each cell of the matrix has a color that represents the score. I would like the user to be able to modify the layout of these cell. To make it easy to the user, I created a template matrix and a button. The user should be able to modify the layout of the cells and on a click of a button, a set of styles (Score 1, Score 2,...) should be generated. Once the matrix is created, the Workbook should be to function without the survey files.
I have tried a couple of things:
Try 1
ThisWorkbook.Styles.Add "Score 1", BasedOn:=cell1
This gives errors. I don't fully understand when they occur, but one of the causes is when the user modifies the cell layout by selecting another style.
Try 2
ThisWorkbook.Styles("Score 1").Delete
ThisWorkbook.Styles.Add "Score 1", BasedOn:=cell1
This is not a good idea: all cells loose their styling when it is executed a second time.
Try 3: Current
Copy the most frequently used properties of the cells layout and copy them to the style. If this style is deleted by the user, it is recreated. This procedures is not ideal, since most style properties won't be covered.
Is there a way to update a cell style that is more general? I would like there to be as little room as possible to make the workbook in an inconsistent and non-functional state.
I sticked with try 3. Because it required a lot of code for all properties that seemed possible to be edited, and because of copying borders is tricky, I post the result.
'xR1_Template: the cell to base the style on
'nm_Style: the name of the style
Public Function Upsert_Style(xR1_Template As Excel.Range, nm_Style As String) As Excel.Style
Dim xStyle As Excel.Style
Set xStyle = Fn.TryGet(ThisWorkbook.Styles, nm_Style)
If Fn.IsNothing(xStyle) Then
Set xStyle = ThisWorkbook.Styles.Add(nm_Style)
End If
xStyle.Font.Color = xR1_Template.Font.Color
xStyle.Font.Bold = xR1_Template.Font.Bold
xStyle.Font.Name = xR1_Template.Font.Name
xStyle.Font.Italic = xR1_Template.Font.Italic
xStyle.Font.Size = xR1_Template.Font.Size
xStyle.Font.Strikethrough = xR1_Template.Font.Strikethrough
xStyle.Font.Subscript = xR1_Template.Font.Subscript
xStyle.Font.Superscript = xR1_Template.Font.Superscript
xStyle.Font.Underline = xR1_Template.Font.Underline
xStyle.Interior.Color = xR1_Template.Interior.Color
xStyle.Interior.Pattern = xR1_Template.Interior.Pattern
xStyle.Interior.PatternColor = xR1_Template.Interior.PatternColor
'NOTE: necessary to delete all borders first. There's no way to delete them one by one.
xStyle.Borders.LineStyle = xlNone
Dim iBorder As Long
For iBorder = 1 To xR1_Template.Borders.Count
Dim xBorder As Excel.Border
'NOTE: The Borders property claims to work with xlBordersIndex argument, but this is not true.
' Normal indexing is used.
Set xBorder = xR1_Template.Borders(iBorder)
'NOTE: "none-style" borders (=no border), should be skipped.
' Once they are retrieved using the Borders property, they are always visible.
' Setting them with xlLineStyle.xlLineStyleNone does not hide them.
If xBorder.LineStyle <> XlLineStyle.xlLineStyleNone Then
Dim xBorder_Style As Excel.Border
Set xBorder_Style = xStyle.Borders(iBorder)
xBorder_Style.Color = xBorder.Color
xBorder_Style.LineStyle = xBorder.LineStyle
xBorder_Style.Weight = xBorder.Weight
End If
Next iBorder
xStyle.AddIndent = xR1_Template.AddIndent
xStyle.FormulaHidden = xR1_Template.FormulaHidden
xStyle.HorizontalAlignment = xR1_Template.HorizontalAlignment
xStyle.IndentLevel = xR1_Template.IndentLevel
xStyle.NumberFormat = xR1_Template.NumberFormat
xStyle.NumberFormatLocal = xR1_Template.NumberFormatLocal
xStyle.Orientation = xR1_Template.Orientation
xStyle.ShrinkToFit = xR1_Template.ShrinkToFit
xStyle.VerticalAlignment = xR1_Template.VerticalAlignment
xStyle.WrapText = xR1_Template.WrapText
xStyle.IndentLevel = xR1_Template.IndentLevel
Set Upsert_Style = xStyle
End Function

openxml sdk excel total sums

i am having difficulties with open xml sdk:
i am trying to generate excel file with several columns that have numbers and i want to have total sum at the end
i have tried to Generate Table Definition Part Content and inside define every column (id, name etC). If column has true for TotalColumn, it adds code (rough example)
var column = new TableColumn{
id = 1,
name = "example",
TotalsRowFunction = TotalsRowFunctionValues.Sum,
TotalsRowFormula = new TotalsRowFormula("=SUBTOTAL(109;[" + rowName + "])")
};
I can't get it to work, when i open excel it reports error, but it doesn't explicitly says what the problem is... I tried with microsoft validator but can't figure anything out...
I'd appreciate any help / example code since i can't google anything out
EDIT:
i use this at the end:
workbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
workbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
Why not use a cell formula?
E.g.
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.CellFormula = new CellFormula(string.Format("=SUBTOTAL({0};[{1}])", "109", rowName));
//This will force a full recalculation of all the cells
workbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
workbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
I ended using EPPlus for this as it seems to be working simple and efficient

Input/Export data through MS Excel into OATS Scripts

When trying to get the Input the data from the Excel Sheet while working with OATS tool, it always gets into the catch block of the function. The below is the script written. Please help us resolve this issue.
public String getInputfromExcel(int argColumnNumber,int argRowNumber)throws Exception
{
String inputExcelName = dataPath+".xlsx";
String cellContent = "12";
try
{
Workbook workbook = Workbook.getWorkbook(new File(inputExcelName));
Sheet sheet = workbook.getSheet(0);
Cell a1 = sheet.getCell(argColumnNumber, argRowNumber);
cellContent = (a1.getContents()).toString();
System.out.println(cellContent.toString());
workbook.close();
}
catch (Exception e)
{
addReport("Getting Input From Excel", "Fail","Exception while reading value from excel sheet");
}
return cellContent;
}
Axel has brought up the point. On a further note, if I remember correctly, the function sheet.getCell(arg1, arg2) has first argument as rowNumber and 2nd as columnNumber (both the values are 0 based index).
Its old quetion....but just posting answer it might be helpful for someone needy.
In Oracle Application Testing Suite. NO NEED of external JARs to read/write data.
You can enable DataTable module in the tool
Complete explanation given here, http://www.testinghive.com/how-to-read-write-excel-in-oats/
//Define Sheet name to be read, and provide comma seperated to read multiple sheets
String sheetName = "Sheet1";
//Mention excel sheet path
String strFile= "C:\\Demo\\test.xls";
//Defined array list to add Sheets to read
List sheetList = new ArrayList();
sheetList.add(sheetName);
// Iports Sheet1
datatable.importSheets(strFile, sheetList, true, true);
//get rowcount
info("Total rows :"+datatable.getRowCount());
int rowcount=datatable.getRowCount();
//Loop to read all rows
for (int i=0;i<rowcount;i++)
{
//Set current row fromw here you need to start reading, in this case start from first row
datatable.setCurrentRow(sheetName, i);
String strCompany=(String) datatable.getValue(sheetName,i,"Company");
String strEmpFName=(String) datatable.getValue(sheetName,i,"FirstName");
String strEmpLName=(String) datatable.getValue(sheetName,i,"LastName");
String strEmpID=(String) datatable.getValue(sheetName,i,"EmpID");
String strLocation=(String) datatable.getValue(sheetName,i,"Location");
//prints first name and last name
System.out.println("First Name : "+strEmpFName+", Last Name : "+strEmpLName);
//Sets ACTIVE column in excel sheet to Y
String strActive="Y";
datatable.setValue(sheetName, i, datatable.getColumn(sheetName, datatable.getColumnIndex("Active")), strActive);
}
//Updates sheet with updated values ie ACTIVE column sets to Y
datatable.exportToExcel("C:\\Demo\\test1.xlsx");

Opening excel file prompts a message box "content recovery of the workbook"

While I'm trying to open excel file a message box is prompting like "We found a problem with some content in file name. Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes.". What actually done is i have a excel template designed and copying the file to another file and created temp file I'm inserting data to temp file using OPEN XML and data is getting from the database.
i have tried the solutions provided in the net but those fixes are not resolving my issue.My excel is 2010
Anyone solution provided is much appreciated.
I had this problem. It was caused by the way I was storing numbers and strings in cells.
Numbers can be stored simply using cell.CellValue = new CellValue("5"), but for non-numeric text, you need to insert the string in the SharedStringTable element and get the index of that string. Then change the data type of the cell to SharedString, and set the value of the cell to the index of the string in the SharedStringTable.
// Here is the text I want to add.
string text = "Non-numeric text.";
// Find the SharedStringTable element and append my text to it.
var sharedStringTable = document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First().SharedStringTable;
var item = sharedStringTable.AppendChild(new SharedStringItem(new Text(text)));
// Set the data type of the cell to SharedString.
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
// Set the value of the cell to the index of the SharedStringItem.
cell.CellValue = new CellValue(item.ElementsBefore().Count().ToString());
This is explained in the documentation here: http://msdn.microsoft.com/en-us/library/office/cc861607.aspx
Another few cases that can cause this type of error:
Your sheet name is longer than 31 characters
You have invalid characters in sheet name
You have cells with values longer than 32k
The issue is due to using
package.Save();
and
package.GetAsByteArray();
at the same time
when we call
package.GetAsByteArray();
it will do following operations
this.Workbook.Save();
this._package.Close();
this._package.Save(this._stream);
Hence, removing
package.Save();
will solve this problem "We found a problem with some content in file name. Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes."
Another possible cause could be exceeded maximum number of cell styles.
You can define:
up to 4000 styles in a .xls workbook
up to 64000 styles in a .xlsx workbook
In this case you should re-use the same cell style for multiple cells, instead of creating a new cell style for every cell.
I added the right cellReference and fixed this issue for me:
string alpha = "ABCDEFGHIJKLMNOPQRSTUVQXYZ";
for (int colInx = 0; colInx < reader.FieldCount; colInx++)
{
AppendTextCell(alpha[colInx] + "1", reader.GetName(colInx), headerRow);
}
private static void AppendTextCell(string cellReference, string cellStringValue, Row excelRow)
{
// Add a new Excel Cell to our Row
Cell cell = new Cell() { CellReference = cellReference, DataType = new EnumValue<CellValues>(CellValues.String) };
CellValue cellValue = new CellValue();
cellValue.Text = cellStringValue.ToString();
cell.Append(cellValue);
excelRow.Append(cell);
}
Same warning but the problem with me was that I was using a client input (name of wave) as sheet name for the file and when date was presented within the name, the character '/' used as date part separator was causing the issue.
I think Microsoft need to provide a better error log to save people time investigate such minor issues. Hope my answer will save someone else's time.
The issue was due to storing a string in the cell directly using cell.CellValue = new CellValue("Text"). It is possible to store numbers like this but not string. For string, define data type as string before assigning the text using Cell.DataType = CellValues.String;

Hiding cell Contains in MS Excel using SpreadSheetGear?

Hey any body know how to hide cell contains using spreadsheet gear.
You can set IRange.NumberFormat to ";;;" to cause the contents of a cell to be hidden. There are also IRange.FormulaHidden, IRange.Rows.Hidden, IRange.Columns.Hidden and probably other ways to approach it that I am not thinking about. Here is some code which demonstrates these approaches:
namespace Program
{
class Program
{
static void Main(string[] args)
{
// Create a new workbook and get a reference to Sheet1!A1.
var workbook = SpreadsheetGear.Factory.GetWorkbook();
var sheet1 = workbook.Worksheets[0];
var a1 = workbook.Worksheets[0].Cells["A1"];
// Put some text in A1.
a1.Value = "Hello World!";
// Set a number format which causes nothing to be displayed.
//
// This is probably the best way to hide the contents of
// a single cell.
a1.NumberFormat = ";;;";
// Set FormulaHidden to true - must set IWorksheet.ProtectContents
// to true for this make any difference. This will not hide values
// in cells.
a1.FormulaHidden = true;
// Hide the row containing A1.
a1.Rows.Hidden = true;
// Hide the column containing A1.
a1.Columns.Hidden = true;
}
}
}

Resources