Google script, manipulate the number value - google-sheets

I have one script behind one spreedsheet and I'm trying to export some cell values to document, and than email the pdv version of temp document..(trash it latter). I have problem with value I get or in the way I'm getting the value from spreedsheet to doc.. I can't manipulate the decimal point..
// fix the price currency display and alignment in GOOGLE DOCUMENT TABLE!
for (var i = 0; i < price.getNumRows(); i++){
for (var j = 0; j < price.getRow(i).getNumCells(); j++){
var temp = price.getCell(i, j);
temp.getChild(0).asParagraph().setSpacingAfter(0);
if((j == 6 || j == 7) && !temp.getText() == "" ) {
(i > 0) ? temp.replaceText(temp.getText(), temp.getText() + " kn") : void false; // skip the first line with header titles...
temp.getChild(0).asParagraph().setAlignment(DocumentApp.HorizontalAlignment.RIGHT);
}
}
}
after (i > 0) there is temp.getText() value.. that sometimes is like: 55,987654 and I would like that to round to two digits.. but can't :(
Thanks for help!

I have found solution..
it's very simple but did take me some time.. hope that can help someone else with similar situation
parseFloat(temp.getText()).toFixed(2) + " kn")
this did the trick and the output is something like: 55,99 kn!

Related

Highlight near duplicate in conditional formating to highlight values with one character difference

I'm currently using this formula to highlight duplicates in my spreadsheet.
=ARRAYFORMULA(COUNTIF(A$2:$A2,$A2)>1)
Quite simple, it allows me to skip the first occurrence and only highlight 2nd, 3rd, ... occurrences.
I would like the formula to go a bit further and highlight near duplicates as well.
Meaning if there is only one character difference between 2 cells, then it should be considered as a duplicate.
For instance: "Marketing", "Marketng", "Marketingg" and "Market ing" would all be considered the same.
I've made a sample sheet in case my requirement is not straightforward to understand.
Thanks in advance.
Answer
Unfortunately, it is not possible to do this only through Formulas. Apps Scripts are need as well. The process for achieving your desired results is described below.
In Google Sheets, go to Extensions > Apps Script, paste the following code1 and save.
function TypoFinder(range, word) { // created by https://stackoverflow.com/users/19361936
if (!Array.isArray(range) || word == "") {
return false;
}
distances = range.map(row => row.map(cell => Levenshtein(cell, word))) // Iterate over range and check Levenshtein distance.
var accumulator = 0;
for (var i = 0; i < distances.length; i++) {
if (distances[i] < 2) {
accumulator++
} // Keep track of how many times there's a Levenshtein distance of 0 or 1.
}
return accumulator > 1;
}
function Levenshtein(a, b) { // created by https://stackoverflow.com/users/4269081
if (a.length == 0) return b.length;
if (b.length == 0) return a.length;
// swap to save some memory O(min(a,b)) instead of O(a)
if (a.length > b.length) {
var tmp = a;
a = b;
b = tmp;
}
var row = [];
// init the row
for (var i = 0; i <= a.length; i++) {
row[i] = i;
}
// fill in the rest
for (var i = 0; i < b.length; i++) {
var prev = i;
for (var j = 0; j < a.length; j++) {
var val;
if (b.charAt(i) == a.charAt(j)) {
val = row[j]; // match
} else {
val = Math.min(row[j] + 1, // substitution
prev + 1, // insertion
row[j + 1] + 1); // deletion
}
row[j] = prev;
prev = val;
}
row[a.length] = prev;
}
return row[a.length];
}
In cell B1, enter =TypoFinder($A$2:$A2,$A2). Autofill that formula down the column by draggin.
Create a conditional formatting rule for column A. Using Format Rules > Custom Formula, enter =B2:B.
At this point, you might wish to hide column B. To do so, right click on the column and press Hide Column.
The above explanation assumes the column you wish to highlight is Column A and the helper column is column B. Adjust appropriately.
Note that I have assumed you do not wish to highlight repeated blank columns as duplicate. If I am incorrect, remove || word == "" from line 2 of the provided snippet.
Explanation
The concept you have described is called Levenshtein Distance, which is a measure of how close together two strings are. There is no built-in way for Google Sheets to process this, so the Levenshtein() portion of the snippet above implements a custom function to do so instead. Then the TypoFinder() function is built on top of it, providing a method for evaluating a range of data against a specified "correct" word (looking for typos anywhere in the range).
Next, a helper column is used because Sheets has difficulties parsing custom formulas as part of a conditional formatting rule. Finally, the rule itself is implemented to check the helper column's determination of whether the row should be highlighted or not. Altogether, this highlights near-duplicate results in a specified column.
1 Adapted from duality's answer to a related question.

FPDFText_SetText change nothing

I can change the text of an pdf text object and pdfium function says "all is ok". But when i save the changed pdf doc no changes are visible. Something is missing and i dont know what.
int co = FPDFPage_CountObjects(page);
for (int j = 0; j < co; ++j) {
FPDF_PAGEOBJECT pobj = FPDFPage_GetObject(page, j);
if (FPDFPageObj_GetType(pobj) == FPDF_PAGEOBJ_TEXT) {
...
if (FPDFText_SetText(pobj, (FPDF_WIDESTRING)L"New Text")) {
std::cout << "#VAL1 was changed\n";
//FPDFPage_GenerateContent(page);
}
}
}
...
FPDF_ClosePage(page);
...
FPDF_FILEWRITE_EX fw;
fw.pFile = fopen("C:\\work\\newpdf.pdf", "wb");
fw.version = 1;
fw.WriteBlock = MyDelegateSaveFunc;
FPDF_SaveAsCopy(doc, &fw, FPDF_NO_INCREMENTAL);
fclose(fw.pFile);
FPDF_CloseDocument(doc);
If i do call GenerateContent (not needed i think) then the whole saved page is empty. I do use the last pdfium binary version 3764.
You need to uncomment the line FPDFPage_GenerateContent(page), after changing the object you need to update the object or generate the whole page.
An empty page after FPDFPage_GenerateContent is a bug already fixed in last builds.

How to compare two column in a spreadsheet

I have 30 columns and 1000 rows, I would like to compare column1 with another column. IF the value dont match then I would like to colour it red. Below is a small dataset in my spreadsheet:
A B C D E F ...
1 name sName email
2
3
.
n
Because I have a large dataset and I want to storing my columns in a array, the first row is heading. This is what I have done, however when testing I get empty result, can someone correct me what I am doing wrong?
var index = [];
var sheet = SpreadsheetApp.getActiveSheet();
function col(){
var data = sheet.getDataRange().getValues();
for (var i = 1; i <= data.length; i++) {
te = index[i] = data[1];
Logger.log(columnIndex[i])
if (data[3] != data[7]){
// column_id.setFontColor('red'); <--- I can set the background like this
}
}
}
From the code you can see I am scanning whole spreadsheet data[1] get the heading and in if loop (data[3] != data[7]) compare two columns. I do have to work on my colour variable but that can be done once I get the data that I need.
Try to check this tutorial if it can help you with your problem. This tutorial use a Google AppsScript to compare the two columns. If differences are found, the script should point these out. If no differences are found at all, the script should put out the text "[id]". Just customize this code for your own function.
Here is the code used to achieve this kind of comparison
function stringComparison(s1, s2) {
// lets test both variables are the same object type if not throw an error
if (Object.prototype.toString.call(s1) !== Object.prototype.toString.call(s2)){
throw("Both values need to be an array of cells or individual cells")
}
// if we are looking at two arrays of cells make sure the sizes match and only one column wide
if( Object.prototype.toString.call(s1) === '[object Array]' ) {
if (s1.length != s2.length || s1[0].length > 1 || s2[0].length > 1){
throw("Arrays of cells need to be same size and 1 column wide");
}
// since we are working with an array intialise the return
var out = [];
for (r in s1){ // loop over the rows and find differences using diff sub function
out.push([diff(s1[r][0], s2[r][0])]);
}
return out; // return response
} else { // we are working with two cells so return diff
return diff(s1, s2)
}
}
function diff (s1, s2){
var out = "[ ";
var notid = false;
// loop to match each character
for (var n = 0; n < s1.length; n++){
if (s1.charAt(n) == s2.charAt(n)){
out += "–";
} else {
out += s2.charAt(n);
notid = true;
}
out += " ";
}
out += " ]"
return (notid) ? out : "[ id. ]"; // if notid(entical) return output or [id.]
}
For more information, just check the tutorial link above and this SO question on how to compare two Spreadsheets.

mixing c# and html in quick succession

I'm trying to build a grid server side, I wrote this in a cshtml file:
#{
var items = (List<FancyItem>)ViewBag.items;
var col = 0;
var colMax = 3;
foreach (var it in items) {
if (col == 0) {<tr>}
if (col == 0) {</tr>}
col++;
if (col == colMax) {col = 0;}
}
}
So in theory, the column creation code would go in between the two if's, however, I never got that far. The two if's are supposed to create rows when the columns reset but it seems everything after < tr> gets interpreted as plain text. I don't know what to do, what kind of syntax candy would fix this?
I see your issue - Razor expects you to close any opening tags or it thinks you are still writing HTML
Try this:
Edit: Added #s to get the content to write to the HTML output stream
foreach (var it in items)
{
if (col == 0)
{
#Html.Raw("<tr>");
}
if (col == 0) {
#Html.Raw("</tr>");
}
col++;
if (col == colMax)
{
col = 0;
}
}

how to randomly select from list of variables (bitmaps) with incremental names using Iterator and/or loop ? (java, blackberry, bb)

I have a big list (say about thousand) of .png bitmaps with incremental names:
_image1 = Bitmap.getBitmapResource("a1.png");
_image2 = Bitmap.getBitmapResource("a2.png");
_image3 = Bitmap.getBitmapResource("a3.png");
...
_image999 = Bitmap.getBitmapResource("a999.png");
_image1000 = Bitmap.getBitmapResource("a1000.png");
I need a code to select one bitmap and attach it to BitmapField myBitmapField, when integer myCounter obtains random value from 1 to 1000. I could do it by checking value of myCounter thousand times by using if and else :
if (myCounter == 1)
myBitmapField.setBitmap(_image1);
else if (myCounter == 2)
myBitmapField.setBitmap(_image2);
else if (myCounter == 3)
myBitmapField.setBitmap(_image3);
...
else if (myCounter == 1000)
myBitmapField.setBitmap(_image1000);
But that would be very long code. Is there a way of doing it using Loop and/or Iterator ? Something like this:
int i = 0;
while (i < 1000)
{
i = i + 1;
if (myCounter == i)
myBitmapField.setBitmap(_image[i]);
}
Is there an easy and short way of doing it ? Thank you very much for help! (Java for blackberry)
What about dynamically generating the name, like
myBitmapField.setBitmap(Bitmap.getBitmapResource("a" + myCounter + ".png"));
If you're concerned about resource duplication, you can check a cache first.

Resources