I'm using google chart API to draw an area chart.
The chart represents an altimetric profile and when I pass the mouse over it, it shows the position (lat and long) from the underlying data table.
So I created my chart:
data = new google.visualization.DataTable(json);
chart = new google.visualization.AreaChart(document.getElementById("chart-output"));
and draw it:
chart.draw(data, options);
and add an handler for the mouseover event
When the event triggers, I want to get the row from the underlying data source
if (event.row != null && event.column != null){
//data is the chart datasource
var o = data.D[event.row];
var sel_x = o.c[0]["coords"]["x"];
var sel_y = o.c[0]["coords"]["y"];
... //show x, y
}
The point is that when the project was first released, last year, everything worked fine and the property data.D actually contained the desired value.
But now, I've found that the same property is undefined and the rows array is found in property data.tf.
I would expect to gain access to the datasource rows through a getter method, but I cannot find the right one. The datatable method ǵetRowProperties(rowIndex) does not provide any content.
What am I doing wrong?
Thanks and regards
**EDIT 12/09 **
#Juvian
Thanks for yr reply, but it's a bit more complicated than that.
My datasource is like this:
{"cols":
[
{"id":"distance","label":"Distance","type":"number"},
{"id":"asfaltocemento","label":"Asphalt/Beton","type":"number"},
{"id":"rocciaghiaia","label":"Fels/Schotter","type":"number"},
{"id":"ghiaccio","label":"Eis","type":"number"},
{"id":"terraprato","label":"Erde/Wiese","type":"number"},
{"id":"sassolastricato","label":"Stein/Pflaster","type":"number"},
{"id":"sconosciuto","label":"Unbekannt","type":"number"}],
"rows":
[
{"c":[{"v":0,"coords": {"x":1296400.1245177952,"y":5885847.104437432,"z":1345.275458520788,"segment_no":0}},{},{"v":1345.275458520788},{},{},{},{}]},
{"c":[{"v":2.8740587294156668,"coords":{"x":1296395.9416741736,"y":5885847.412533606,"z":1345.4754191288682,"segment_no":0}},{},{"v":1345.4754191288682},{},{},{},{}]},
{"c":[{"v":17.583008965075226,"coords":{"x":1296374.532888888,"y":5885848.966197753,"z":1346.3169989102385,"segment_no":0}},{},{"v":1346.3169989102385},{},{},{},{}]},
{"c":[{"v":23.830815143830804,"coords":{"x":1296365.4205057025,"y":5885849.273363226,"z":1346.724445260275,"segment_no":0}}, {},{"v":1346.724445260275},{},{},{},{}]},
....
]}
When I get the event from the graphic, I retrieve the needed values this way:
var o = data.tf[event.row];
var sel_x = o.c[0]["coords"]["x"];
var sel_y = o.c[0]["coords"]["y"];
I know it's not a good practise to use property (tf) and I should use accessor like getValue(), but using the getValue method I can't access 'coords' object and its subobject.
Any help will be appreciated
Well, data.d is not a public method, so google can make changes to that, you should use public methods instead for consistency.
Try this:
var sel_x = data.getValue(event.row, 0); // supposing your x value is in fisrt column
var sel_y = data.getValue(event.row, 1); // supposing your y value is in second column
More info here: Google DataTable
Related
My sheet is a query-sheet from database. Some of them contain html hex-code color which I need to manually use edit>Find and Replace every time it is refreshed.
I am very new to Google App Script and been trying to use the following code:
function Clearcode() {
var lookupone = new RegExp(/{color:#.{7}/);
var rep = "";
var spreadSheet = SpreadsheetApp.getActive();
var querySheet = spreadSheet.getSheetByName("QUERY");
var lastRow = querySheet.getLastRow();
var lastColumn = querySheet.getLastColumn();
var data = querySheet.getRange(2, 1, lastRow-1, lastColumn).getValues();
var textfinder = querySheet.createTextFinder(lookupone);
var found = textfinder.replaceAllWith(rep);
return (found);
}
Yet, when I run this function in the sheet it did not work. Any thought?
P.S. I planned to eliminated "[color]" part of the hex-code as well by create the similar function.
P.S.2 I have attached a snapshot of a table as you requested. The red line is just for confidentiality of the data. Below the line is just a normal text.
Pay attention to types!
CreateTextFinder accepts String as argument NOT a regexp object.
To use strings as regular expressions, useRegularExpressions needs to be set to true
querySheet.createTextFinder("\\{color:#?.{0,6}\\}")//only 6 characters
.useRegularExpressions(true)
.replaceAllWith("")
I have a column of E-mail addresses in a Google Sheet and want to remove all of the domain names and '#' symbol and copy this to a new column. For example:
Column-A
test#test.com
testb#gmail.com
testc#yahoo.com
Copied and removing the domains to:
Column-B
test
testb
testc
all you need is:
=ARRAYFORMULA(IFNA(REGEXEXTRACT(A1:A&"", "(.+)#")))
use this function on google App script:
function myFunction() {
// Your spreadsheet
var ss = SpreadsheetApp.getActive()
//if you got only one sheet
var sheet = ss.getSheets()[0];
// This is in the case that your sheet as a header, if not replace 2 by 1 and (sheet.getLastRow()-1) by sheet.getLastRow()
var valuesColumnA = sheet.getRange(2,1,(sheet.getLastRow()-1)).getValues();
//Just to have each value in the same array
var valuesColumnAMapped = valuesColumnA.map(function(r){return r[0]});
valuesColumnAMapped.forEach(function(value, index){
var split = value.split("#");
sheet.getRange((index+2),2).setValue(split[0]);
})
}
My answer as per my understanding maybe I'm wrong so please follow if I'm right to understand.
use split to get this
Go to Data
Click on Split Text to Columns
Pick Custom From Drop Down
enter # and you get your result.
guys!
I'm new to this website and also not good with coding. So I would really appreciate some help.
Right now I'm in need of a specific code to make a google sheet work perfectly.
To further explain:
I have a google sheet that a few information will be input by other co-workers. What I need is a code that will register the date in a specific cell and by whom the input was made on another cell.
So far this is what I have:
function onEdit(event) {
var sheet = event.source.getSheetByName("Input");
// Note: actRng = return the last cell of the row modified
var actRng = event.source.getActiveRange();
var index = actRng.getRowIndex();
var cindex = actRng.getColumnIndex();
// Note: date = return date
// Note: user = return the user email
var userCell = sheet.getRange(index,14);
var dateCell = sheet.getRange(index,2);
var inputdate = Utilities.formatDate(new Date(), "GMT+0200", "yyyy-MM-dd");
// Note(with hour): var inputdate = Utilities.formatDate(new Date(), "GMT+0200", "yy-MM-dd HH:mm");
//var user = event.user; // Note: event.user will not give you collaborator's Id
var user = Session.getEffectiveUser();
// Note: setValue = Insert in the cell the date when this row was modified
if (userCell.Value == null) {
userCell.setValue(user);
dateCell.setValue(inputdate)
}
}
My main problems/questions are:
I don't exactly need the last modifier, but the person who first input info on the cells. Therefore I tried that last IF (If the cell that is supposed to have the last modifier e-mail is blank, it means that nobody changed that row before, so the code should add the user on the userCell), although it is not working since every change I make it ignores the verification.
I also want to add that the event will only happen if you add values, if you delete them, nothing happens. (so far even when I delete cells, it counts as modification)
Most of the sheet is protected to avoid that people by accident erase some of the formulas, so the cells that this code changes are also protected. Is there a way to make the code bypass cell protection?
Please, help me identify what I'm doing wrong and hopefully I'll get this working perfectly! Thanks for the help !
If you want to prevent the script from firing when a cell is deleted, try:
var editedCell = SpreadsheetApp.getActiveSheet().getRange(e.range.getRow(), e.range.getColumn());
if (editedCell == "") {
return;
}
I would change Session.getEffectiveUser() to session.getActiveUser().
The last if statement is unnecessary. You want whoever most recently edited the field to be identified, along with the date.
I'm using the Google Visualizations gauge on a page, but it's important that the value its displaying is not shown as a label right below the needle.
I've found two ways of doing this. Once you navigate through the DOM to the gauge widget, and navigating into the SVG pieces, you can either set the textContent element to be an empty string, or you can delete that whole text label entity, entirely.
function removeLabel(widget) {
var gauge_label_parent = widget.getElementsByTagName("g")[1];
var gauge_label = gauge_label_parent.getElementsByTagName("text")[0];
gauge_label.textContent = "";
// Another way of getting rid of the text: remove the element
// gauge_label_parent.removeChild(gauge_label);
}
The problem is: both of those techniques work only on the first time. If I re-draw the gauge with updated values, then the label re-appears, and trying to remove the label element or set textContent="" does nothing.
So, instead of just being able to update the value with:
data.setValue(0, 1, newValue);
chart.draw(data, options);
I have discovered that I have to change the options a little bit, like:
data.setValue(0, 1, newValue);
options.minorTicks = 3; // Change the options somehow
chart.draw(data, options); // Tell gauge to draw that
options.minorTicks = 2; // Change the options back to what they were
chart.draw(data, options); // Draw again
Here's a fiddle to see how it works or doesn't. Set the fixLabel to true or false depending upon whether you want the label problem to be present or not. Keep in mind that the label will (properly) be missing the first time. It re-appears when you update its value.
http://jsfiddle.net/jemenake/72dMt/2/
So, a few questions:
Any idea why it's doing this?
Is there a way to remove the label without having to go through this option-changing business?
Bonus question: Am I unclear about how minorTicks is supposed to work, or is it broken? The docs say that it's supposed to be the number of minor ticks between majors, but setting it to 2 gives me only 1 minor tick, 3 gives me 2, etc. And, if I set it to 0 or 1, I get "Problem parsing d=''" in the console.
Adding to Madthews answer:
To those of you who are trying to remove the label from the Google Gague Chart.
If you add the following code into your page (i have placed it in the header to keep things tidy) then you can set the font size of the Label to whatever you want.
<style>
* {text-rendering: optimizeLegibility; font-size:100%;}
svg g g {font-size:0px;}
</style>
I have been toying around with this for a while now and the top line of the css above is essential otherwise it will not work!
Ok I'll try to answer:
1) Label options are not managed by current API release
https://google-developers.appspot.com/chart/interactive/docs/gallery/gauge
Workaround: try with this CSS
svg g g {
font-size:0px;
}
http://jsfiddle.net/Madthew/72dMt/17/
Above fiddle explains you the meaning of the minorThicks. It's correct that if you set 2 you get 3 "spaces". Minor thicks represent the number of "BLANK" spaces between two major thicks. In the example you will se the perfect matching between your arrow and the thin line representing the minor thick.
Instead of messing with styles, you could just insert the value with a blank formatted field.
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Unitless Indicator', {v:counter, f:''} ]
]);
This also works with addRows.
jsfiddle here: https://jsfiddle.net/08x2m4vo/2/
Use this. This is also labelled by Google.
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['', {v: <Your_own_value_of_the_gauge_meter>, f: ''}],
]);
In place of "<Your_own_value_of_the_gauge_meter>" use your value variable. That's it.
What about this?
['Label', 'Value'],
['', 80]
Can somebody please tell me how can i show the Total Collection on MSChart
You can use chart.Annotations property to get a similar result.
For example with the following code (located after filling the chart):
var ann = new RectangleAnnotation();
ann.Text = "Total Collection" + Environment.NewLine + "250 Billion";
ann.IsMultiline = true;
ann.AxisX = this.chart1.ChartAreas[0].AxisX;
ann.AxisY = this.chart1.ChartAreas[0].AxisY;
ann.AnchorX = 9; // as you can see from the image below,
ann.AnchorY = 41; // these values are inside the range
// add the annotation to the chart annotations list
this.chart1.Annotations.Add(ann);
I got the following result:
N.B.:
there are a lot of annotations types (CalloutAnnotation, EllipseAnnotation...) and they have a lot of properties to change styles and behaviors. You can even set a property to allow annotation moving (i.e. AllowMoving=true).
Have a look to annotation properties through intellisense or MSDN.
You can set the property IsDockedInsideChartArea to true. You will also need to specify which ChartArea the legend is docked to, and set the position property to Auto.
legend.IsDockedInsideChartArea = true;
legend.DockedToChartArea = "ChartArea1";
There are more information about this and other legend properties here.