Hiding cell Contains in MS Excel using SpreadSheetGear? - hide

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;
}
}
}

Related

Excel office script - copy a row to a new tab if cell is NOT empty

I have created a script that will move an entire row to another tab on the worksheet if certain text is entered into a selected cell.
I want to be able to do this if the cell is not empty rather than having certain text and I would like the row to be deleted all except the first column.
The script is below and works really well, I'm not great at coding and managed to cobble this together from some other scripts i found but i now can't manage to edit it to fit this new task.
I tried using Javascript not equals signs and other symbols and can remove rows that are empty but i can't seem to make it work.
function main(workbook: ExcelScript.Workbook) {
// You can change these names to match the data in your workbook.
const TARGET_TABLE_NAME = 'TableNAdded';
const SOURCE_TABLE_NAME = 'TableN';
// Select what will be moved between tables.
const FILTER_COLUMN_INDEX = 27;
const FILTER_VALUE = 'Y';
// Get the Table objects.
let targetTable = workbook.getTable(TARGET_TABLE_NAME);
let sourceTable = workbook.getTable(SOURCE_TABLE_NAME);
// If either table is missing, report that information and stop the script.
if (!targetTable || !sourceTable) {
console.log(`Tables missing - Check to make sure both source (${TARGET_TABLE_NAME}) and target table (${SOURCE_TABLE_NAME}) are present before running the script. `);
return;
}
// Save the filter criteria currently on the source table.
const originalTableFilters = {};
// For each table column, collect the filter criteria on that column.
sourceTable.getColumns().forEach((column) => {
let originalColumnFilter = column.getFilter().getCriteria();
if (originalColumnFilter) {
originalTableFilters[column.getName()] = originalColumnFilter;
}
});
// Get all the data from the table.
const sourceRange = sourceTable.getRangeBetweenHeaderAndTotal();
const dataRows: (number | string | boolean)[][] = sourceTable.getRangeBetweenHeaderAndTotal().getValues();
// Create variables to hold the rows to be moved and their addresses.
let rowsToMoveValues: (number | string | boolean)[][] = [];
let rowAddressToRemove: string[] = [];
// Get the data values from the source table.
for (let i = 0; i < dataRows.length; i++) {
if (dataRows[i][FILTER_COLUMN_INDEX] === FILTER_VALUE) {
rowsToMoveValues.push(dataRows[i]);
// Get the intersection between table address and the entire row where we found the match. This provides the address of the range to remove.
let address = sourceRange.getIntersection(sourceRange.getCell(i, 0).getEntireRow()).getAddress();
rowAddressToRemove.push(address);
}
}
// If there are no data rows to process, end the script.
if (rowsToMoveValues.length < 1) {
console.log('No rows selected from the source table match the filter criteria.');
return;
}
console.log(`Adding ${rowsToMoveValues.length} rows to target table.`);
// Insert rows at the end of target table.
targetTable.addRows(-1, rowsToMoveValues)
// Remove the rows from the source table.
const sheet = sourceTable.getWorksheet();
// Remove all filters before removing rows.
sourceTable.getAutoFilter().clearCriteria();
// Important: Remove the rows starting at the bottom of the table.
// Otherwise, the lower rows change position before they are deleted.
console.log(`Removing ${rowAddressToRemove.length} rows from the source table.`);
rowAddressToRemove.reverse().forEach((address) => {
sheet.getRange(address).delete(ExcelScript.DeleteShiftDirection.up);
});
// Reapply the original filters.
Object.keys(originalTableFilters).forEach((columnName) => {
sourceTable.getColumnByName(columnName).getFilter().apply(originalTableFilters[columnName]);
});
}
If I understand your question correctly, you are currently filtering the table if the value = "Y" (the value assigned to FILTER_VALUE). This part is happening here:
if (dataRows[i][FILTER_COLUMN_INDEX] === FILTER_VALUE) {
You'd like to update this line from checking if the cell value is Y to checking if the cell value is not empty. To do this, you can update this line like so:
if (dataRows[i][FILTER_COLUMN_INDEX] as string !== "") {

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

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);

Find value on any sheet in spreadsheets using Google Script

Using the code below I'm able to look through multiple sheets in a spreadsheet to find the first value that equals the selected cell. The only problem with this bit is: The cell with the value found is highlighted yellow, but the cell with the value found isn't selected. See code below for hopping through sheets. I can't get my head around this :)
Funny thing is that the code for highlighting and selecting a value does work when I'm not hopping through the list of sheets, see the best answer: Find value in spreadsheet using google script
function SearchAndFind() {
//determine value of selected cell
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
var value = cell.getValue();
//create array with sheets in active spreadsheet
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
//loop through sheets to look for value
for (var i in sheets) {
//Set active cell to A1 on each sheet to start looking from there
SpreadsheetApp.setActiveSheet(sheets[i])
var sheet = sh.getActiveSheet();
var range = sheet.getRange("A1");
sheet.setActiveRange(range);
//set variables to loop through data on each sheet
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var data = sheets[i].getDataRange().getValues()
var step = 0
//loop through data on the sheet
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log(step+' -- '+value+' = '+data[r][c]);
if(data[r][c]==''||step==1){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
sheet.getRange(r+1,c+1).activate().setBackground('#ffff55');
return;
}
}
}
}
}
This code is able to search across multiple sheets, it is obviously based on your published code but uses a memory (scriptProperties) to keep the search value 'alive' when changing from one sheet to the next one and to know when to search for it.
It has 2 non-optimal aspects : 1° you have to keep searching up to the last occurrence before you can begin a new search.
2° : when it switches from sheet n to sheet n+1 it first selects cell A1 before finding the value occurrence.
I guess it should be possible to get rid of these issues but right now I don't find how :-)
Maybe the approach is simply not the best, I started from a simple one sheet script modified and complexified... that's usually not the best development strategy (I know), but anyway, it was a funny experiment and a good logic exercise ...
Thanks for that.
function SearchAndFind() {
//determine value of selected cell
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
var value = cell.getValue();
if(ScriptProperties.getProperty('valueToFind')!=''){value = ScriptProperties.getProperty('valueToFind')};
//create array with sheets in active spreadsheet
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets()
var sheetNumber = sheets.length;
var currentSheet = ss.getIndex()-1;
Logger.log(currentSheet);
//loop through sheets to look for value
for (var i = currentSheet ; i<sheetNumber ; ++i ){
Logger.log('currentSheet = '+i)
//Set active cell to A1 on each sheet to start looking from there
SpreadsheetApp.setActiveSheet(sheets[i])
// sheets[i].getRange(1,1).activate();
//set variables to loop through data on each sheet
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var data = sheets[i].getDataRange().getValues()
var step = 0;
//loop through data on sheet
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log('sheet : '+i+' step:'+step+' value '+value+' = '+data[r][c]);
if(data[r][c]==''||(step==1&&i==currentSheet)){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
sheets[i].getRange(r+1,c+1).activate().setBackground('#ffff55');
ScriptProperties.setProperty('valueToFind',value);
return;
}
}
}
cell = sheets[i].getRange(1,1);
}
ScriptProperties.setProperty('valueToFind','');
Logger.log('reset');
}

Find value in spreadsheet using google script

Situation:
1 spreadsheet
multiple sheets
1 cell selected (may vary)
What I'd like to do is to find and set focus to the next cell in any sheet that matches the selected cell (case insensitive) upon clicking a button-like image in the spreadsheet. Sort of like a custom index MS Word can create for you.
My approach is:
- set value of the selected cell as the variable (succeeded)
- find the first cell that matches that variable (not the selected cell) (no success)
- set value of found cell as variable2 (no success)
- set the focus of spreadsheet to variable2 (no success)
function FindSetFocus()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var activecell = sheet.getActiveCell();
var valueactivecell = activecell.getValue();
//here comes the code :)
}
I have found this snippet in the following topic, but I'm having a little trouble setting the input and doing something with the output: How do I search Google Spreadsheets?
I think I can replace 'value' with 'valueactivecell', but I don't know how to set the range to search through all sheets in the spreadsheet. Also, I'd like the output to be something I can set focus to using something like 'ss.setActiveSheet(sheet).setActiveSelection("D5");'
/**
* Finds a value within a given range.
* #param value The value to find.
* #param range The range to search in.
* #return A range pointing to the first cell containing the value,
* or null if not found.
*/
function find(value, range) {
var data = range.getValues();
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
if (data[i][j] == value) {
return range.getCell(i + 1, j + 1);
}
}
}
return null;
}
also found this but no luck on getting it to work on the selected cell and setting focus: How do I search for and find the coordinates of a row in Google Spreadsheets best answer, first code.
Please bear in mind that I'm not a pro coder :) If code samples are provided, please comment inline hehe.
Thanks in advance for any help.
Edit 24/10: Used the code from the answer below and edited it a bit. Now able to look through multiple sheets in a spreadsheet to find the value. The only problem with this bit is: My cell is highlighted yellow, but the cell with the value found isn't selected. See code below for hopping through sheets. I can't get my head around this :)
function SearchAndFind() {
//determine value of selected cell
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
var value = cell.getValue();
//create array with sheets in active spreadsheet
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
//loop through sheets to look for value
for (var i in sheets) {
//Set active cell to A1 on each sheet to start looking from there
SpreadsheetApp.setActiveSheet(sheets[i])
var sheet = sh.getActiveSheet();
var range = sheet.getRange("A1");
sheet.setActiveRange(range);
//set variables to loop through data on each sheet
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var data = sheets[i].getDataRange().getValues()
var step = 0
//loop through data on the sheet
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log(step+' -- '+value+' = '+data[r][c]);
if(data[r][c]==''||step==1){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
sheet.getRange(r+1,c+1).activate().setBackground('#ffff55');
return;
}
}
}
}
}
Here is an example of such a function, I inserted a drawing in my spreadsheet representing a button which I assigned the script so it's easy to call.
I added a feature to set a light yellow background on the resulting selected cell so it's easier to see the selected cell but this is optional.
Code
function findAndSelect(){
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
cell.setBackground('#ffff55');// replace by cell.setBackground(null); to reset the color when "leaving" the cell
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var value = cell.getValue();
var data = ss.getDataRange().getValues();
var step = 0
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log(step+' -- '+value+' = '+data[r][c]);
if(data[r][c]==''||step==1){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
ss.getRange(r+1,c+1).activate().setBackground('#ffff55');
return;
}
}
}
}
Caveat
This code only searches 'downwards', i.e. any occurrence in a row that would precede the selected cell is ignored, same for columns...
If that's an issue for you then the code should be modified to start iterating from 0. But in this case if one need to ignore the initial starting cell then you should also memorize its coordinates and skip this value in iteration.

Get and use user data from another sheet in Google Docs

We use google spreadsheets for reporting by quite a big number of users.
I have written a basic script, which opens a specific sheet depending on the current user:
var CurrentUser = Session.getUser().getEmail()
var ss = SpreadsheetApp.getActive();
switch(CurrentUser){
case "usermail1#gmail.com":
SpreadsheetApp.setActiveSheet(ss.getSheetByName("sheet1"));
break;
case "usermail2#gmail.com":
SpreadsheetApp.setActiveSheet(ss.getSheetByName("sheet2"));
break;
case "usermail3#gmail.com":
SpreadsheetApp.setActiveSheet(ss.getSheetByName("sheet3"));
break;
etc...
I would like to put the userdata and sheetnames into an external table and get these data depending on that table, so it is easier to maintain the list of e-mails and users.
How can I get data from a specific google spreadsheet and let the script work according to that?
You can try this. It simulates a VLOOKUP on a different sheet and switches to the 'matched' sheet in your current workbook. This doesn't handle non-matches, but that should be relatively straightforward to add to suit your case.
function switchSheets() {
// Current sheet
var ss = SpreadsheetApp.getActive();
// Target sheet (using the key found in the URL)
var target = SpreadsheetApp.openById("my_other_sheet_id");
var rows = target.getDataRange();
var values = rows.getValues();
// Get the current user
var CurrentUser = Session.getUser().getEmail();
// Now iterate through all of the rows in your target sheet,
// looking for a row that matches your current user (this assumes that
// it will find a match - you'll want to handle non-matches as well)
for (var i = 1; i <= rows.getNumRows() - 1; i++) {
// Match the leftmost column
var row = values[i][0];
if (row == CurrentUser) {
// If we match, grab the corresponding sheet (one column to the right)
target_sheet = values[i][1];
break;
}
}
// Now switch to the matched sheet (rememeber to handle non-matches)
ss.setActiveSheet(ss.getSheetByName(target_sheet));
};

Resources