How to format spreadsheet columns using ColdFusion? - coldfusion

I am using SpreadsheetFormatColumns() to format the columns in a spreadsheet to "text", but I don't know how to do this, all the formats in the livedocs are for numbers, currency or dates... is there something like
SpreadsheetFormatColumns(mySpreadsheet, {dataFormat="text"}, "1-15")
out there? this is really bugging me...
Thanks

In ColdFusion 9.0.1 (i.e. updater 1), if you use SpreadsheetSetCellValue() it will respect the format you have previously set. So to force a column to be text when populating a sheet you can use a 3-step process:
Populate the spreadsheet, ignoring the incorrectly interpreted number values.
Format the column you want as text.
Replace the incorrect value in each row of the column with the correct value, which will now be treated as text.
Here's an example which you can copy into a .cfm and run as-is (requires CF9.0.1)
<cfscript>
// Create a 2 column, 2 row query. The first column contains numbers or possible numbers we want formatted as text in our spreadsheet
q = QueryNew( "" );
QueryAddColumn( q,"NumbersAsText","VarChar",[ 01050094071094340000,"743059E6" ] );
QueryAddColumn( q,"Text","VarChar",[ "abc","def" ] );
// Get the column names as an array so we can get at them more easily later
columns = q.getMetaData().getColumnLabels();
// Create a new spreadsheet object
sheet = SpreadSheetNew( "test" );
// specify the column we want formatted as text
forceTextColumnNumber = 1;
// Use the query column names as column headers in our sheet
SpreadSheetAddRow( sheet,q.columnList );
// Add the data: the numbers will be inserted as numeric for now
SpreadSheetAddRows( sheet,q );
// Now we format the column as text
SpreadSheetFormatColumn( sheet,{ dataformat="text" },forceTextColumnNumber );
// Having formatted the column, add the column from our query again so the values correct
while( q.next() )
{
// Skip the header row by adding one
rownumber = ( q.currentrow + 1 );
// Get the value of column at the current row in the loop
value = q[ columns[ forceTextColumnNumber ] ][ q.currentrow ];
// replace the previously added numeric value which will now be treated as text
SpreadsheetSetCellValue( sheet,value,rownumber,forceTextColumnNumber );
}
// Download the object as a file
sheetAsBinary = SpreadSheetReadBinary( sheet );
filename = "test.xls";
</cfscript>
<cfheader name="Content-Disposition" value="attachment; filename=#Chr(34)##filename##Chr(34)#">
<cfcontent type="application/msexcel" variable="#sheetAsBinary#" reset="true">
By default, both of the values in the first column of my query would be treated as numbers (the second as a HEX). Using this method both preserve their original value as text.

According to this chart use '#' (without quotes) for the text placeholder.

Related

Google Sheets: How can I extract partial text from a string based on a column of different options?

Goal: I have a bunch of keywords I'd like to categorise automatically based on topic parameters I set. Categories that match must be in the same column so the keyword data can be filtered.
e.g. If I have "Puppies" as a first topic, it shouldn't appear as a secondary or third topic otherwise the data cannot be filtered as needed.
Example Data: https://docs.google.com/spreadsheets/d/1TWYepApOtWDlwoTP8zkaflD7AoxD_LZ4PxssSpFlrWQ/edit?usp=sharing
Video: https://drive.google.com/file/d/11T5hhyestKRY4GpuwC7RF6tx-xQudNok/view?usp=sharing
Parameters Tab: I will add words in columns D-F that change based on the keyword data set and there will often be hundreds, if not thousands, of options for larger data sets.
Categories Tab: I'd like to have a formula or script that goes down the columns D-F in Parameters and fills in a corresponding value (in Categories! columns D-F respectively) based on partial match with column B or C (makes no difference to me if there's a delimiter like a space or not. Final data sheet should only have one of these columns though).
Things I've Tried:
I've tried a bunch of things. Nested IF formula with regexmatch works but seems clunky.
e.g. this formula in Categories! column D
=IF(REGEXMATCH($B2,LOWER(Parameters!$D$3)),Parameters!$D$3,IF(REGEXMATCH($B2,LOWER(Parameters!$D$4)),Parameters!$D$4,""))
I nested more statements changing out to the next cell in Parameters!D column (as in , manually adding $D$5, $D$6 etc) but this seems inefficient for a list thousands of words long. e.g. third topic will get very long once all dog breed types are added.
Any tips?
Functionality I haven't worked out:
if a string in Categories B or C contains more than one topic in the parameters I set out, is there a way I can have the first 2 to show instead of just the first one?
e.g. Cell A14 in Categories, how can I get a formula/automation to add both "Akita" & "German Shepherd" into the third topic? Concatenation with a CHAR(10) to add to new line is ideal format here. There will be other keywords that won't have both in there in which case these values will just show up individually.
Since this data set has a bunch of mixed breeds and all breeds are added as a third topic, it would be great to differentiate interest in mixes vs pure breeds without confusion.
Any ideas will be greatly appreciated! Also, I'm open to variations in layout and functionality of the spreadsheet in case you have a more creative solution. I just care about efficiently automating a tedious task!!
Try using custom function:
To create custom function:
1.Create or open a spreadsheet in Google Sheets.
2.Select the menu item Tools > Script editor.
3.Delete any code in the script editor and copy and paste the code below into the script editor.
4.At the top, click Save save.
To use custom function:
1.Click the cell where you want to use the function.
2.Type an equals sign (=) followed by the function name and any input value — for example, =DOUBLE(A1) — and press Enter.
3.The cell will momentarily display Loading..., then return the result.
Code:
function matchTopic(p, str) {
var params = p.flat(); //Convert 2d array into 1d
var buildRegex = params.map(i => '(' + i + ')').join('|'); //convert array into series of capturing groups. Example (Dog)|(Puppies)
var regex = new RegExp(buildRegex,"gi");
var results = str.match(regex);
if(results){
// The for loops below will convert the first character of each word to Uppercase
for(var i = 0 ; i < results.length ; i++){
var words = results[i].split(" ");
for (let j = 0; j < words.length; j++) {
words[j] = words[j][0].toUpperCase() + words[j].substr(1);
}
results[i] = words.join(" ");
}
return results.join(","); //return with comma separator
}else{
return ""; //return blank if result is null
}
}
Example Usage:
Parameters:
First Topic:
Second Topic:
Third Topic:
Reference:
Custom Functions
I've added a new sheet ("Erik Help") with separate formulas (highlighted in green currently) for each of your keyword columns. They are each essentially the same except for specific column references, so I'll include only the "First Topic" formula here:
=ArrayFormula({"First Topic";IF(A2:A="",,IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))) & IFERROR(CHAR(10)&REGEXEXTRACT(REGEXREPLACE(LOWER(B2:B&C2:C),IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))),""),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))))})
This formula first creates the header (which can be changed within the formula itself as you like).
The opening IF condition leaves any row in the results column blank if the corresponding cell in Column A of that row is also blank.
JOIN is used to form a concatenated string of all keywords separated by the pipe symbol, which REGEXEXTRACT interprets as OR.
IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))) will attempt to extract any of the keywords from each concatenated string in Columns B and C. If none is found, IFERROR will return null.
Then a second-round attempt is made:
& IFERROR(CHAR(10)&REGEXEXTRACT(REGEXREPLACE(LOWER(B2:B&C2:C),IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))),""),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>"")))))
Only this time, REGEXREPLACE is used to replace the results of the first round with null, thus eliminating them from being found in round two. This will cause any second listing from the JOIN clause to be found, if one exists. Otherwise, IFERROR again returns null for round two.
CHAR(10) is the new-line character.
I've written each of the three formulas to return up to two results for each keyword column. If that is not your intention for "First Topic" and "Second Topic" (i.e., if you only wanted a maximum of one result for each of those columns), just select and delete the entire round-two portion of the formula shown above from the formula in each of those columns.

How to extract values from a text string using a number as delimiter?

I have a bit of a unique situation, I have a column of data that has text values:
Column
sdfsadf42lkjdflk
skld35kdfosdffj
kdfjsi78ldsfjoi
Result should look like:
Column
42lkjdflk
35kdfosdffj
78ldsfjoi
Is there a way to cut out everything before a number? A generalized way would be nice in the event that number currently not included can still be evaluated for (the instance of a number always being used is the only constant)
You can try finding the index and then slicing the str using the same index. I will show you with an example.
var str = "skld35kdfosdffj";
var firstDigit = str.search(/\d/);
str = str.slice(firstDigit,str.length);
console.log(str);
Assuming your column is named ColumnName, in powerquery, add custom column with formula
= Text.RemoveRange([ColumnName], 0, Text.PositionOfAny([ColumnName],{"0".."9"}))

How to collect data and headers for non blank cells in a row in Sheets

I cannot find a solution to my problem:
I have a sheet with ~290 rows and ~80 columns. The first row and column are fixed/header.
I would like to collect non-blank values and their header into column B.
I've tried to search for solutions, but I'm not as good at excel, so I cannot wrap my head around most of the advice that I've found.
In Google Sheets you could use an Array formula. I got this:
The formula I've used:
=ArrayFormula(CONCATENATE(IF(--(C2:G2<>"")*COLUMN($C$1:$G$1)<>0;$C$1:$G$1&" "&C2:G2;"")))
This is how it works:
(--(C2:G2<>"") will return an array of 0 and 1 if the cell is blank or not
COLUMN($C$1:$G$1) will return an array of column numbers of each cell
(C2:G2<>"")*COLUMN($C$1:$G$1) we multiply both arrays, so we will get an array of column numbers of non blank cells and 0 of blank cells
<>0;$C$1:$G$1&" "&C2:G2;"") We check if each number in the array obtained in step 3 is 0 or not. If it's 0, it returns a null value, if not, it returns the value of cell
CONCATENATE will concatenate all values from previous array (step 4) so we concatenate null values with real values of non blank cells.
Not sure if this will make the sheet load slower if you have too many records.
Hope this helps
Excel is not the same Google Sheets
=ARRAYFORMULA(TRIM(REGEXREPLACE(
TRANSPOSE(
QUERY(TRANSPOSE(IF(C2:F13<>"",C1:F1 & ", ","")),,99^99)
),
"((\s+)|(,\s*$))",
" "
)))
My sample
use:
=ARRAYFORMULA(REGEXREPLACE(TRIM(TRANSPOSE(QUERY(TRANSPOSE(
IF(C2:G<>"", C1:G1&" "&C2:G&",", )),,99^99))), ",$", ))

Removing a row containing a specific text in Google Sheets

I have a data set of around 3000 columns, but some of the columns have several cells that contain cells "na". These rows have no importance since they don't have data that I will need, is there a command in google sheets that can either highlight the entire row that contains that text or delete the entire row containing that text?
Any help would be appreciated.
https://docs.google.com/spreadsheets/d/1u8OUfQOzgAulf1a8bzQ8SB5sb5Uvb1I4amF5sdGEBlc/edit?usp=sharing
My document ^.
you can use this formula to color all na rows:
=ARRAYFORMULA(REGEXMATCH(TRANSPOSE(QUERY(TRANSPOSE($A1:$Z),,999^99)), " na "))
This answer based on what I understand, sorry if I'm wrong. You can use conditional formatting to highlight all NA text
This is what rules I used
Here are another answers that may help you
Delete a row in Google Spreadsheets if value of cell in said row is 0 or blank
Google Sheets: delete rows containing specified data
Deleting Cells in Google Sheets without removing a whole row
Sorry for bad English.
I'm not sure if my understing is well but see below what you can do.
This is a google script function which color the whole column where "na" is in
function myFunction() {
//get the spreadsheet where the function is running
var ss = SpreadsheetApp.getActive()
//Replace "the name of your sheet" by your sheet name" be careful its case sensitive.
var sheet = ss.getSheetByName("The name of your sheet")
//Get all your data as an array (If your sheet has no header, change 2 by 1 and (sheet.getLastRow()-1) by sheet.getLastRow())
var values = sheet.getRange(2,1,(sheet.getLastRow()-1), sheet.getLastColumn()).getValues();
//For each column
for (var i = 0; i< sheet.getLastColumn(); i++){
//using function map is helping to select one column by one column
var mapValues = values.map(function(r){return r[i]});
//Searching your keyword in the column, in your case it's "na"
var position = mapValues.indexOf("Put the string that you are looking for, in your case 'na'");
//if at least there is one "na" inside the column
if( position >-1){
//then this color have to get red color as a background
var wholeColumn = sheet.getRange(2,(i+1),(sheet.getLastRow()-1));
wholeColumn.setBackground("red");
}
}
}``
Let me know if it works

Calculated text column for Google Line Chart x-axis not working

Changing my Line Chart's x-axis labels from one bit of text to another bit of text isn't working; what am I doing wrong, please?
I have a Line Chart whose discrete x-axis is labeled with text representations of the date.
(I'm using corechart; I've created a dataTable, created a dataView based off of that, and have created the chart as a ChartWrapper).
I'm filtering the dataView based on the textual date, so my initial x-axis domain values are in the format 2013-09-01... and that works. But now I need to change the x-axis labels to the format 9/2013. The examples I've found on this seem clear, but the chart isn't drawn but is replaced by an error: "c is null". Googling that, the problem sounds like my domain column is the wrong data type, but I don't see how that's possible.
Can you please point out my error? Below, I've gotten the list of columns that I need displayed; that would be a list like [0,3,5] where 0 is the domain column. I remove it first so I can set the new, formatted column:
// Format the x-axis as n/Y
// remove unformatted column 0;
view_col_list.splice(0, 1);
data_displayed.setColumns([
{
role: 'domain',
calc: function(dataTable, row) {
var my_date = new Date(dataTable.getValue(row, 0));
console.info('the date I want to format: %o',my_date);
// this does in fact produce "9/2013"
console.info('the date I want to show' + my_date.getMonth() + '/' + my_date.getFullYear());
return my_date.getMonth() + '/' + my_date.getFullYear();
},
type: 'string',
sourceColumn: 0,
id: 0
},
view_col_list
]);
I would guess that your dates are probably not the problem, but there are a few things I would recommend changing with them: remove the "sourceColumn" attribute, as it isn't needed; and change the way you are constructing your new date string, as converting a string to a Date object is inconsistent across browsers. Also, the #getMonth method returns the 0-indexed month, so "2013-09-01" would get turned into "8/2013" in your code (assuming the date string conversion works). There is an easier way that doesn't involve converting to Date objects and back into strings:
var dateArray = dataTable.getValue(row, 0).split('-');
return dateArray[1] + '/' + dateArray[0];
I suspect the problem is caused by this:
view_col_list.splice(0, 1);
data_displayed.setColumns([{...}, view_col_list]);
which is equivalent to data_displayed.setColumns([{...}, [...]]); which definitely won't work. Rather than splice the first element from the view_col_list, replace it with your object:
view_col_list[0] = {...};
data_displayed.setColumns(view_col_list);