How to delete hidden Column/Row from Excel Sheet? - excel

I am trying to delete all the hidden columns from Excel sheet and i am using Microsoft Office Interop.
Problem is when i iterate through columns i didn't find the column hidden property set.
I don't know what am I doing wrong here.
Any help would be appreciated
int columnCount = wsCurrent.UsedRange.Columns.Count;
Excel.Worksheet wsCurrent = (Excel.Worksheet)wsEnumerator.Current;
for (int c = 1; c <= columnCount; c++)
{
if (wsCurrent.UsedRange.get_Range((Excel.Range)wsCurrent.UsedRange.Cells[1, c], (Excel.Range)wsCurrent.UsedRange.Cells[wsCurrent.Rows.Count, c]).EntireColumn.Hidden)
Console.WriteLine("Column Hidden");
}

By the way your code does not have "r" variable declaration which you are using.
Use next code to iterate cells and determine if cell is hidden:
const double SIZE = 0.5;
int cols = sheet.UsedRange.Columns.Count;
int rows = sheet.UsedRange.Rows.Count;
Range usedRange = sheet.UsedRange;
for (int iCol = 1; iCol <= cols; iCol++)
{
for (int jRow = 1; jRow <= rows; jRow++)
{
Range cellRng = (Excel.Range)usedRange.Cells[jRow, iCol];
if (double.Parse(cellRng.ColumnWidth.ToString()) <= SIZE ||
double.Parse(cellRng.RowHeight.ToString()) <= SIZE)
{
/*do your stuff here*/
}
}
}
Like this way. Constant Size is needed becouse cell could be almost hidden, but visualy it will be hidden. Code must be optimized, but concept is clear.

Related

Getting all values from all table

i couldn't ask my question very well. I put here a table that i want to create in google sheet, excel or other. Anyone can help me please?
street name
number
Impasse Malabane
9
Impasse Malabane
Impasse du Puech
Impasse Bimet
Rue Levers
Impasse du Puech
1 bis
9
1 bis
6
26
Rue Levers
26
5
2 bis
2
28
Impasse Bimet
6
8
1
Impasse Bimet
2
8 bis
Impasse Malabane
5
Impasse du Puech
2 bis
Impasse Malabane
8
Impasse Malabane
8 bis
Impasse du Puech
1
Rue Levers
28
In Google Sheets, assuming that your original headers "Street Name" and "Number" are in A1 and B1 (with the data in A2:B), place this in D2:
=ArrayFormula(TRANSPOSE(TRIM({UNIQUE(FILTER(A2:A,A2:A<>"")),TO_TEXT(SPLIT(TRANSPOSE(TRIM(SPLIT(TEXTJOIN("| ",1,{IFERROR(SUBSTITUTE(VLOOKUP(UNIQUE(FILTER(A2:A,A2:A<>""))&TRANSPOSE(UNIQUE(FILTER(B2:B,B2:B<>""))),A2:A&B2:B,1,FALSE),UNIQUE(FILTER(A2:A,A2:A<>"")),"")),SEQUENCE(COUNTA(UNIQUE(FILTER(A2:A,A2:A<>""))),1,1,0)})&"|","| 1|",0,1))),"|"))})))
This one formula will generate all results. As you add new data in A2:B, it will be added without any need to edit the formula.
This should work in Google Apps Script:
function myFunction() {
// initialize
var ss = SpreadsheetApp.getActiveSheet();
var lr = ss.getLastRow();
var values = ss.getRange(2,1,lr-1,2).getValues();
console.log(values.sort());
var result = [];
console.log(result);
var prevCol = '';
// populate array
for (i = 0; i < values.length; i++) {
if (values[i][0] != prevCol) {
result.push([values[i][0], values[i][1]]);
}
else {
result[result.length-1].push(values[i][1]);
}
prevCol = values[i][0];
}
console.log(result);
// transpose array
var newArray = [];
for(var i = 0; i < result.length; i++){
newArray.push([]);
};
for(var i = 0; i < result.length; i++){
for(var j = 0; j < result.length; j++){
newArray[j].push(result[i][j]);
};
};
// write to range
var dest = ss.getRange(2,4,newArray[0].length,newArray.length);
dest.setValues(newArray);
}
It's a little difficult to understand the question, but I think you are trying to convert a 2-column table into a multi-column table with data.
You can do this with an array formula. First, copy all your distinct street names into a single row. In the picture below, this was done in cells F1:I1.
Cell F2 formula:
{=IFERROR(INDEX($B$2:$B$9999, SMALL(IF($F$1=$A$2:$A$9999, ROW($A$2:$A$9999)-ROW($A$2)+1), ROW(1:1))),"")}
You need to press CTRL+SHIFT+ENTER to get those curly brackets to make this an array formula. Drag it down as far as you need, well beyond as many rows as you would expect. It's wrapped in an IFERROR handler to show a blank if no more results are found.
The formulas for the other columns are similar. You just need to change the reference from $F$1 to $G$1 and so on, and also repeat the array trick.
Also, if you have more than 9999 rows, just adjust the end row number in the formula.
This VBA script does it. Assuming your data starts in A1 in Sheet1.
Sub transform()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim first_col As String: first_col = "A"
Dim ws2 As Worksheet
Dim c_last As Range
Dim c As Range
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim key As Variant
Dim arr() As String
Set c_last = ws.Cells(ws.Rows.Count, first_col).End(xlUp)
For Each c In ws.Range(first_col & 2, c_last)
If dict.Exists(Trim(c)) Then
dict.Item(Trim(c)) = dict.Item(Trim(c)) & "$" & CStr(c.Offset(, 1))
Else
dict.Item(Trim(c)) = CStr(c.Offset(, 1))
End If
Next
Set ws2 = ws.Parent.Sheets.Add(After:=ws.Parent.Worksheets(ws.Parent.Worksheets.Count))
Set c = ws2.Range("A1")
For Each key In dict.Keys()
c = key
arr = Split(dict.Item(key), "$")
c.Offset(1).Resize(UBound(arr) + 1) = Application.Transpose(arr)
Set c = c.Offset(, 1)
Next
End Sub
Before:
After:
A correction of Carlos' proposal (Google Sheets) :
function myFunction() {
// initialize
var ss = SpreadsheetApp.getActiveSheet();
var lr = ss.getLastRow();
var values = ss.getRange(2,1,lr-1,2).getValues();
values.sort();
var result = [];
var prevCol = '';
// populate array
for (i = 0; i < values.length; i++) {
if (values[i][0] != prevCol) {
result.push([values[i][0], values[i][1]]);
}
else {
result[result.length-1].push(values[i][1]);
}
prevCol = values[i][0];
}
// determine maximum length
var max = 0 ;
for(var i = 0; i < result.length; i++){
max=Math.max(max,result[i].length);
};
// complete the array by replacing null values with an empty string
for (var i = 0; i < result.length; i ++) {
for (var j = 0; j < max; j ++) {
if (result[i][j] == null) {result[i][j] = "";}
}
}
// transpose array
var result = transpose(result);
// write to range
ss.getRange(2,4,result.length,result[0].length).setValues(result);
}
function transpose(a){
return Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
}

Excel table to DataTable (VSTO)

I have an Excel VSTO Add-in, and I have to get excel table data into a DataTable class, I've already implemented it by looping through the cells but its a bit slow:
DataTable dataTable = new DataTable(table.Name);
foreach (Excel.ListColumn column in table.ListColumns)
dataTable.Columns.Add(column.Name);
for (int r = 2; r < table.ListRows.Count + 2; r++)
{
DataRow row = dataTable.NewRow();
for (int c = 1; c < table.ListColumns.Count + 1; c++)
row[c - 1] = ((Excel.Range)table.Range[r, c]).Value;
dataTable.Rows.Add(row);
}
So my question is, is there any Method (or fast way) in Excel interop to export table data to a DataTable class?
Thanks
You can read all values in the DataBodyRange of your table (a ListObject I deduce) at once, into a 1-based 2D object array, like so:
var theValues = table.DataBodyRange.Value;
It's then just a matter of scanning this array.

C# NPOI set cell style to Text / string 1-19 is formatted as a date / disable any formating

I am creating an excel, when i write some values example 1-19, when I open the excel doc, i see 1-19, but if i click on it then excel tries to format it as a date
IS THERE A WAY to force the sheet to not use any formulas or formatting?
I have checked and the dataformat is string.
private void Test1(ref ISheet worksheet, string[] array, IWorkbook workbook, int iRow, XSSFFont font2)
{
var format = HSSFDataFormat.GetBuiltinFormats();
ICellStyle _TextCellStyle = workbook.CreateCellStyle();
_TextCellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("#");
IRow file = worksheet.CreateRow(iRow);
int iCol = 0;
for (int y = 0; y < array.Length; y++)
{
ICellStyle style = workbook.CreateCellStyle();
style.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
//style.DataFormat = HSSFDataFormat.
ICell cell = file.CreateCell(iCol, CellType.String);
cell.SetCellValue(array[y]);
style.SetFont(font2);
// cell.CellStyle = style;
var getst = cell.CellType;
cell.CellStyle = _TextCellStyle;
iCol++;
getst = cell.CellType;
}
}
Your data remains in "General" format even after you are using correct format string "#" as per documentation. Some time library methods don't work in NPOI so you'll have to try different approach.
You can try one of these
_TextCellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("text"); //Instead of "#"
Or prefix single quote for data when writing it for excel file like '1-19

How to override PrimeFaces p:dataExporter wrongly exporting numbers as text in Excel?

The PrimeFace p:dataExporter tag exports numeric data as text by default, which results in a cell with a green triangle in the upper left corner. This can be seen in the PrimeFaces showcase example as well, if you click the Excel export under the cars table.
How can I override this default to make sure my numeric columns are not exported as text? I tried using the postProcessor attribute pointing to my method that sets the Excel format for all the data cells using POI API but that did not take effect (did not change anything):
public void formatExcel(Object doc) {
HSSFWorkbook book = (HSSFWorkbook)doc;
HSSFSheet sheet = book.getSheetAt(0);
HSSFRow header = sheet.getRow(0);
int colCount = header.getPhysicalNumberOfCells();
int rowCount = sheet.getPhysicalNumberOfRows();
HSSFCellStyle numStyle = book.createCellStyle();
numStyle.setDataFormat((short)1);
for(int rowInd = 1; rowInd < rowCount; rowInd++) {
HSSFRow row = sheet.getRow(rowInd);
for(int cellInd = 1; cellInd < colCount; cellInd++) {
HSSFCell cell = row.getCell(cellInd);
String val = cell.getStringCellValue();
cell.setCellStyle(numStyle);
}
}
}
I also tried
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
but that gives me
java.lang.IllegalStateException: Cannot get a numeric value from a text cell
So that means that all data is indiscriminately exported as text and then you can't even change it afterwards.
This is what ended up working for me. It is far from elegant but it works:
HSSFCellStyle intStyle = book.createCellStyle();
intStyle.setDataFormat((short)1);
HSSFCellStyle decStyle = book.createCellStyle();
decStyle.setDataFormat((short)2);
HSSFCellStyle dollarStyle = book.createCellStyle();
dollarStyle.setDataFormat((short)5);
for(int rowInd = 1; rowInd < rowCount; rowInd++) {
HSSFRow row = sheet.getRow(rowInd);
for(int cellInd = 1; cellInd < colCount; cellInd++) {
HSSFCell cell = row.getCell(cellInd);
//This is sortof a hack to counter PF exporting all data as text
//We capture the existing value as string, convert to int,
//then format the cell to be numeric and reset the value to be int
String strVal = cell.getStringCellValue();
//this has to be done to temporarily blank out the cell value
//because setting the type to numeric directly will cause
//an IllegalStateException because POI stupidly thinks
//the cell is text because it was exported as such by PF...
cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
strVal = strVal.replace(",", StringUtils.EMPTY);
if(strVal.indexOf('.') == -1) {
//integer
//numStyle.setDataFormat((short)1);
int intVal = Integer.valueOf(strVal);
cell.setCellStyle(intStyle);
cell.setCellValue(intVal);
} else {
//double
if(strVal.startsWith("$")) {
strVal = strVal.replace("$", StringUtils.EMPTY);
//numStyle.setDataFormat((short)5);
cell.setCellStyle(dollarStyle);
} else {
//numStyle.setDataFormat((short)2);
cell.setCellStyle(decStyle);
}
double dblVal = Double.valueOf(strVal);
cell.setCellValue(dblVal);
}
}
}
In your postProcessor, you nowhere set the value of the cell to an integer. You set the type, but not the value. Setting the type is not enough. You have to convert value to a number and set it again

How to count cell numbers based on a set of numbers

I am looking for a function which counts how many numbers in a range of cells are in the set of numbers
For example I have the set of numbers(1,2,3) and my cells contains 1 | 2 | 3 | 4 | 5 | 3 , the count should return 4
I have tried using countif but no success, I would like to have an excel function Ex.: =countif(A1:D5,...)
How about this? Assume data is in range A1:D5 and you want to count cells with a value of 1, 2 or 3:
=SUM(COUNTIF(A1:D5, {"1","2","3"}))
I hope my pseudo-code would be understandable
int count(int *set, int set_size, int *cells, int cells_size)
{
int v = 0;
// For every number in set
for(int i = 0; i < set_size; ++i)
{
// Loop through every number in cells
for(int j = 0; j < cells_size; ++j)
{
// If number in cells equals number in set, increment v
if(cells[j] == set[i])
{
v++;
}
}
}
// Result is in v, return it
return v;
}
Of course you can optimize a bit with using better containers than just arrays and sizes of them, but I hope you get the basics from this.
Note I used C-like language for pseudo-code, if anything is unclear I can explain further.

Resources