I wrote this function, the last line seems wrong* but it actually works. Can someone explain how does this stuff work ?
function convertEncoding(str,from,to) {
var charSetObj = createobject("java", "java.nio.charset.Charset");
var e_to = charsetObj.forName(from);
var e_from = charsetObj.forName(to);
return e_from.decode(e_to.encode(str)).toString();
}
I am on BlueDragon 7 and 7.1JX (not the open source)
I was inspired from this function : http://acoderslife.com/index.cfm/blog/Converting-Text-From-UTF-8-to-ISO-8859-1
* It seems that our last action is to work with the From encoding. It should be From.decode(string) and then To.encode(decoded_string)
The reason it seems off is that you swapped the variable names, so they do not accurately represent the contents:
var e_to = charsetObj.forName(from); // Original encoding
var e_from = charsetObj.forName(to); // New encoding
The reason it works is because the final statement accounts for this by swapping the variables positions, so that despite their names, the code is actually doing this:
return newEncoding.decode( originalEncoding.encode(str) ).toString();
Obviously best to fix the variable names, so you are not scratching your head when you run across this code six months from now.
function convertEncoding(str, from, to) {
var charSetObj = createobject("java", "java.nio.charset.Charset");
var origEncoding = charsetObj.forName( arguments.from );
var newEncoding = charsetObj.forName( arguments.to );
return newEncoding.decode(origEncoding.encode( arguments.str )).toString();
}
Related
I ve been getting some issues trying to use IF statement using items on the sheets as answers, mostly i been trying either using as firt statement a string directly or using another cell of the sheets with the statement comparing to the one i ve been trying to detect with out any results. Mostly my objective would be to, with a daly trigger, use an IF statement to detect every day if the date of today is the same as a date marked on a cell, my only current solution is and only thing is to make it detect if a cell is empty or not, so i just been using google Formulas that do the detect of the date, and if True make it empty, and if not make something appear
Here are some of the tests I ve been trying
Test 1:
var Sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SheetName");
else if (Sheet.getRange(1, 1).getValue() == "2/2/2020"){}
(cell A1=2/2/2020)
Test 2:
var Sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SheetName");
else if (Sheet.getRange(1, 1).getValue() == Sheet.getRange(1, 2).getValue()){}
(cell A1=2/2/2020)
(cell B1=2/2/2020)
Here are two solutions depending on what you are trying to accomplish.
This first one gets the values, formats them to a date format, and then compares them
function myFunction() {
var tz = Session.getScriptTimeZone();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('SheetName');
var data = sheet.getDataRange().getValues();
var aVal = Utilities.formatDate(data[0][0],tz,'MM/dd/YYYY');
var bVal = Utilities.formatDate(data[0][1],tz,'MM/dd/YYYY');
Logger.log([aVal,bVal])
if(aVal == bVal) {
//do something
}
}
This second section gets the display values and compares them. The first solution compares the date values while this second solution compares the dates as a string. Good luck!
function myFunction1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('SheetName');
var data = sheet.getDataRange().getDisplayValues();
var aVal = data[0][0]
var bVal = data[0][1]
Logger.log([aVal,bVal])
if(aVal == bVal) {
//do something
}
}
I have this google script for google sheets that moves rows of data from "Sheet1" to "Sheet2" when column 15 says "tracking", and it works perfectly fine when I type in "tracking" but I would like that column to be an IF equation something like IF(G:G="tracking not available at this time","","tracking"). But the code does not seem to recognize the formula change from "" to "tracking". Do I need to change the getvalue()? Or is there a different workaround to this issue? I've used =query(importrange) withing the spreadsheet to copy over data with a trigger word, but I really want this to be more of an archive system and add a row to the bottom of "Sheet2" whenever row15 on "sheet1"Thanks! Here is the code:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Sheet1" && r.getColumn() == 14 && r.getValue() == "tracking") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Sheet2");
if(targetSheet.getLastRow() == targetSheet.getMaxRows()) {
targetSheet.insertRowsAfter(targetSheet.getLastRow(), 20);
}
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
I had an issue with this recently
I spent about 3 hours debugging something yesterday and this was the culprit.
try using r.getDisplayValue() instead of r.getValue
I am still new to this myself, and feel free to correct me if I am wrong, because if there is a different reason I would really love to know!!!
It seems that if a value in a cell is not typed in but placed there through a formula such as =query() or a similar method, I don't think it actually sees that there is a value in the cell. (I got null values or the formula itself)
If you use getDisplayValue, it "should" get the value that you actually see in the cell.
The correct way to get formulas, instead of displayed values, is with getFormulas rather than getValues
Also found on...
https://github.com/System-IO-Abstractions/System.IO.Abstractions/issues/393
(But there's a wider audience here)
In a test I have the following:
var testSettings = new ApplicationSettings() { DefaultLedgerFilename = testLedgerFilename };
//Add the byte array as file data
var fileData = new MockFileData(testSettings); //I added an overload PR #389
//Create a file system with the fake data as a "file"
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ AppDomain.CurrentDomain.BaseDirectory+"MoneyTrackerConfig.config", fileData }
});
In the codebase I have the following:
var tempFile = _fileSystem.FileInfo.FromFileName(_path);
if (tempFile.Exists && (tempFile.Length > 0))
{
...
The problem is when I run the test 'tempFile.Exists' returns 'false'. Even if I create the file on the drive it returns 'false'. What am I doing wrong?
Found the issue.
After a day of debugging (that included digging into and debugging the System.IO.Abstractions source) I realized that I missed a backslash.
Yup, pure user error. Note the line above
{ AppDomain.CurrentDomain.BaseDirectory+"MoneyTrackerConfig.config", fileData }
... it should be ...
{ AppDomain.CurrentDomain.BaseDirectory+#"\MoneyTrackerConfig.config", fileData }
Sorry for anyone that took this seriously. I feel ridiculous.
I have taken a bit of script from Serge which is great (original link here. I have added in a second criteria to exclude certain rows and it works great except, if there is not header in the sheet being copied to, it will not work (error: "The coordinates or dimensions of the range are invalid.") and if I enter a header or some other data, it overwrites it. Can anyone assist please? I have also found that is there is no match to the criteria I get following message "TypeError: Cannot read property "length" from undefined."
Also, what change would I need to make to change the cell 'dataSheetLog[i][12]' to the status variable, i.e. "COPIED" after I have copied it across. I have tried writing a setValue line but it is obviously the wrong instruction for that syntax.
Code is:
{
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetLog = Spreadsheet.getSheetByName("LOG");
var sheetMaint = Spreadsheet.getSheetByName("MAINTENANCE");
var Alast = sheetLog.getLastRow();
var criteria = "08 - Maintenance"
var status = "COPIED"
var dataSheetLog = sheetLog.getRange(2,1,Alast,sheetLog.getLastColumn()).getValues();
var outData = [];
for (var i in dataSheetLog) {
if (dataSheetLog[i][2]==criteria && dataSheetLog[i][12]!=status){
outData.push(dataSheetLog[i]);
}
}
sheetMaint.getRange(sheetMaint.getLastRow(),1,outData.length,outData[0].length).setValues(outData);
}
In:
sheetMaint.getRange(sheetMaint.getLastRow(),1,outData.length,outData[0].length).setValues(outData);
getLastRow() refers to the last occupied row and should be ,getLastRow() + 1,to keep from overwriting your headers and other problems.
Edited:
{
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetLog = Spreadsheet.getSheetByName("LOG");
var sheetMaint = Spreadsheet.getSheetByName("MAINTENANCE");
var Alast = sheetLog.getLastRow(); // Log
var criteria = "08 - Maintenance"
var status = "COPIED"
var dataSheetLog = sheetLog.getRange(2,1,Alast,sheetLog.getLastColumn()).getValues(); //Log
var dataSheetLogStatusRange = sheetLog.getRange(2,13,Alast,1); //Log
var dataSheetLogStatus = dataSheetLogStatusRange.getValues(); //Log
var outData = [];
for (var i =0; i < dataSheetLog.length; i++) {
if (dataSheetLog[i][2]==criteria && dataSheetLog[i][12]!=status){
outData.push(dataSheetLog[i]);
dataSheetLogStatus[i][0] = "COPIED";
}
}
if(outData.length > 0) {
sheetMaint.getRange(sheetMaint.getLastRow() + 1,1,outData.length,outData[0].length).setValues(outData);
dataSheetLogStatusRange.setValues(dataSheetLogStatus);
}
}
}
what change would I need to make to change the cell
'dataSheetLog[i][12]' to the status variable, i.e. "COPIED" after I
have copied it across.
You were trying to update the value in the array that was extracted from the sheet and not the sheet itself. As arrays are zero based and spreadsheets are not, to translate, +1 must be added to array row and column indices. I am assuming status is in column M of your sheet.
I have absolutely no knowledge in Regex whatsoever. Basically what I'm trying to do is have an error class that I can use to call errors (obviously) which looks like this:
package avian.framework.errors
{
public class AvError extends Object
{
// errors
public static const LAYER_WARNING:String = "Warning: {0} is not a valid layer - the default layer _fallback_ has been used as the container for {1}.";
/**
* Constructor
* Places a warning or error into the output console to assist with misuse of the framework
* #param err The error to display
* #param params A list of Objects to use throughout the error message
*/
public function AvError(err:String, ...params)
{
trace(err);
}
}
}
What I want to be able to do is use the LAYER_WARNING like this:
new AvError(AvError.LAYER_WARNING, targetLayer, this);
And have the output be something along the lines of:
Warning: randomLayer is not a valid layer - the default layer _fallback_ has been used as the container for [object AvChild].
The idea is to replace {0} with the first parameter parsed in ...params, {1} with the second, etc.
I've done a bit of research and I think I've worked out that I need to search using this pattern:
var pattern:RegExp = /{\d}/;
You can use StringUtil
var original:String = "Here is my {0} and my {1}!";
var myStr:String = StringUtil.substitute(original, ['first', 'second']);
Using the g flag in RegExp you can create an array containing all of your {x} matches, then loop through this array and replace each of the matches with the appropriate parameter.
Code:
var mystring:String = "{0} went to {1} on {2}";
function replace(str:String, ...params):String
{
var pattern:RegExp = /{\d}/g;
var ar:Array = str.match(pattern);
var i:uint = 0;
for(i; i<ar.length; i++)
{
str = str.split(ar[i]).join(params[i]);
}
return str;
}
trace(replace(mystring, "marty", "work", "friday")); // marty went to work on friday
i'm assuming you want to have several static constants with varying replacement instances ({0}, {1}, {2}, etc.) in each string constant.
something like this should work - sorry, it's untested:
public function AvError(err:String, ...params)
{
var replacementArray:Array = err.match(new RegExp("{\\d}", "g"));
for (var i:int = 0, i < replacementArray.length, i++)
err = err.replace(new RegExp(replacementArray[i], "g"), params[i]);
trace(err);
}
if you do have several static constants with varying replacement instances, you'll want to check for an appropriate matching amount of …params that are passed.