BIRT Palette scripting: How to access dataset row - birt

If I want to change the color of circles in scatter chart based on a field not being used in the chart, then how do i use that column in script. I mean how can i get the that data...for example
If (row[v_count])>2
fill red color...
The exact code is below
function beforeDrawDataPoint(dph, fill, icsc)
{
//Fill implements Fill interface
//ImageImpl
//ColorDefinitionImpl
//GradientImpl
//MultipleFillImpl
//EmbeddedImageImpl
//PatternImageImpl
importPackage( Packages.org.eclipse.birt.chart.model.attribute.impl );
val = dph.getOrthogonalValue();
if( fill.getClass().isAssignableFrom(ColorDefinitionImpl)){
if (row[v_count]>2){
fill.set(255, 0, 0);
}
}
}
but i dont know do i get that v_count column in the script. is there some function to get that column ?
I mean if we are making some calculations based on a column from databinding columns..that is not being used in x or y axis, then how do we access that column in the script..is there some kind of function for that.. I tried row["v_count"], but it is not working.
Arif

You could use "persistent global variables". In any place of your report you can write the following to store and load a global variable. Note that you cannot store Integers but only Strings (but after loading you can cast your Strings back to other types). You could store the Value of your column in the Script of an invisible data field located above your chart, so inside your chart you can read the value.
//store a value
reportContext.setPersistentGlobalVariable("varName", "value");
//load the value
var load = reportContext.getPersistentGlobalVariable("varName");

I spend my day look but I did not find the solution, this is my colleague who give me :)
So I share.
in my example I had to create a vertical marker for every new year
function beforeGeneration(chart, icsc)
{
importPackage(Packages.org.eclipse.birt.chart.model.component.impl);
importPackage(Packages.org.eclipse.birt.chart.model.data.impl);
importPackage(Packages.org.eclipse.birt.chart.model.attribute);
importPackage(Packages.org.eclipse.birt.chart.model.attribute.impl);
var chart = icsc.getChartInstance();
var yAxis = chart.getBaseAxes()[0];
//get date series for my case
series = yAxis.getRuntimeSeries();
// but if you have multiple series ... (for exemple xaxis)
for (i = 0; i < series.length; i++){
var values = series[i].getDataSet().getValues();
for (j = 0; j < values.length; j++){
if(j > 1){
var date1 = values[j-1];
var date2 = values[j];
if(date1.getYear() < date2.getYear()){
min_ml = MarkerLineImpl.create(yAxis, NumberDataElementImpl.create(j));
min_ml.getLabel().getCaption().setValue("Nouveau boitier");
min_ml.getLineAttributes().getColor().set(255,0,0);
}
}
}
}
}

Related

Google Apps Script For Loop To Grab Cell Values and Insert into Formula

I have 5 possible locations where a user can enter either: "Yes, No, or any URL". If a URL is entered, I need the value of that cell (the URL) to be entered into an equation on a corresponding cell in a separate sheet. Here is what I have:
//Locations of the cells where the user can enter the URL.
var graphic1_loc = 'A62';
var graphic2_loc = 'A63';
var graphic3_loc = 'A64';
var graphic4_loc = 'A65';
var graphic5_loc = 'A66';
//The corresponding locations on the "Briefing" sheet where the images would get inserted.
var graphic1_placement = 'B45';
var graphic2_placement = 'B46';
var graphic3_placement = 'B47';
var graphic4_placement = 'B48';
var graphic5_placement = 'B49';
//main_gen is the name of the sheet where the user enters the data. This just grabs the value
//the user entered and stores it in the corresponding variable.
var graphic1 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic1_loc).getValue();
var graphic2 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic2_loc).getValue();
var graphic3 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic3_loc).getValue();
var graphic4 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic4_loc).getValue();
var graphic5 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic5_loc).getValue();
var graphics_placements = ["B45", "B46", "B47", "B48", "B49"]; //These are the corresponding cells where the image would be placed on a separate sheet.
//If any graphic is a URL, insert that image into it's corresponding cell in the Briefing tab.
for (var num = 0; num < 5; num ++) {
var graphicformula = '=IMAGE("' + graphic[num] + '",1)';
if (graphic[num].length > 5) {
SpreadsheetApp.getActiveSheet().getRange('Briefing!'+graphic[num]_placement).setFormula(graphicformula);
}
}
What I am trying to get the If statement within the For Loop to say is...If the length of the value of graphic1 is > 5 (if it isn't yes (3) or no (2) then it is assumed it is a URL) then find the corresponding cell on the "Briefing" sheet to insert the formula. The current way I have it written is not correct, but I wanted to attempt to write something to give you an idea of what I am after. Thanks for any help you can provide!
You want to run SpreadsheetApp.getActiveSheet().getRange('Briefing!'+graphic[num]_placement).setFormula(graphicformula); when the value of graphic# is URL.
For example, when the URL is in the cell A63 in the sheet main_gen, you want to put the formula of =IMAGE(URL,1) to the cell B46 in the sheet Briefing
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
In your script, you are trying to use graphic[num] as a variable of graphic1, graphic2,,,. In this case, this cannot be used as the variable.
In your situation, the cells A62:A66 in the sheet main_gen are correspoinding to the cells B45:B49 in the sheet Briefing. I think that this can be used for modifying your script.
The values of the cells A62:A66 in the sheet main_gen can be retrieved by ss.getSheetByName("main_gen").getRange("A62:A66").getValues().
In order to confirm whether the value of cell is the URL, in this modification, I used test().
I think that when the destination sheet is declared out of the for loop, the process cost can be reduced.
When above points are reflected to your script, it becomes as follows.
Modified script:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getSheetByName("main_gen").getRange("A62:A66").getValues();
var dstSheet = ss.getSheetByName("Briefing");
var graphics_placements = ["B45", "B46", "B47", "B48", "B49"];
for (var num = 0; num < source.length; num ++) {
if (/https?:\/\//.test(source[num][0])) {
var graphicformula = '=IMAGE("' + source[num][0] + '",1)';
dstSheet.getRange(graphics_placements[num]).setFormula(graphicformula);
}
}
References:
test()
getValues()
If I misunderstood your question and this was not the direction you want, I apologize.

Dependent dynamically populated dropdown list Google Sheet

I would simply like to autopopulate the Point Segment with all the segments linked to a specific Street, when the Street name is inputted.
When Street name is inputted into column C, Column D should have a dropdown containing only the point segments of that street.
While I realize this can simply be achieved by creating a filter in the Data tab, I am trying to create a form which does not allow this and therefore need to script it.
This is the Google sheet:
https://docs.google.com/spreadsheets/d/1QbTqPegE_GLj9V6x5uCNNXAoi0v12Pmaelhc7uaMknE/edit?usp=sharing
I have written this code, however I am having trouble filtering by Street.
function setDataValid_(range, sourceRange) {
var rule = SpreadsheetApp.newDataValidation().requireValueInRange(sourceRange,
true).build();
range.setDataValidation(rule);
}
function onEdit() {
var aSheet = SpreadsheetApp.getActiveSheet();
var aCell = aSheet.getActiveCell();
var aColumn = aCell.getColumn();
if (aColumn == 3 && aSheet.getName() == 'Sheet1') {
var range = aSheet.getRange(aCell.getRow(), aColumn + 1);
var sourceRange = aSheet.getRange('Sheet1!B2:B5131');
setDataValid_(range, sourceRange)
}
}
Any help would be much appreciated.
You're close, but you should use requireValueInList instead of requireValueInRange. You were passing sourceRange, which is equal to all of the point segments.
To accomplish the filtering, you need to look at all of the street values. If the street value matches the selection, then save the adjacent point segment to a separate list. Once you've saved all those point segments, then pass it to requireValueInList. To do this, you need to take advantage of getValues() to get the range values as an array and loop through it.
I've made a few other modifications:
In onEdit, you should use the an event object
Changed your variable names so they would be easier to understand
Added a check to make sure that the Street cell isn't blank (no need to trigger the action when you delete a value from the cell)
Added a function getPointSegments that does the filtering
Removed the setDataValid_ function as it made your code less readable, and in my opinion, wasn't worthy of being its own function
function onEdit(event) {
var eventSheet = event.range.getSheet();
var eventCell = event.range;
var eventColumn = eventCell.getColumn();
var eventValue = eventCell.getValue();
if (eventColumn == 3 && eventSheet.getName() == "Sheet1" && eventValue != "") {
var pointRange = eventSheet.getRange(eventCell.getRow(), eventColumn + 1);
var pointSegments = getPointSegments_(eventSheet, eventValue);
var rule = SpreadsheetApp.newDataValidation().requireValueInList(pointSegments, true).build();
pointRange.setDataValidation(rule);
}
}
function getPointSegments_(sheet, selectedStreet) {
var streetsAndPoints = sheet.getRange("A2:B").getValues();
var pointSegments = [];
for (var i=0; i<streetsAndPoints.length; i++) {
var street = streetsAndPoints[i][0];
var pointSegment = streetsAndPoints[i][1];
if (street === selectedStreet)
pointSegments.push(pointSegment);
}
return pointSegments;
}
Lastly, be sure that your data validations in the Street field look like this (and I would actually suggest "Reject input" on invalid data).

Is there a way to mass input data validation in google sheets

I'm trying to create a drop down menu with contents based on a another cell in the same row. For example if A1 = 'yes' then the drop down in B2 gives you the options of 'yes' or 'no'. I can do this I have the list data set up and to code works. The problem is I need to do this 155 times in 4 different sheets. Is there a faster way to do this than right clicking and editing the data validation rules for each cell. Here's a link to the test sheet I'm working on :
https://docs.google.com/spreadsheets/d/1rd_Ig_wpof9R_L0IiA1aZ9syO7BWxb6jvBhPqG8Jmm4/edit?usp=sharing
You can set data validation rules with a script, as documented here. Here's a reference for starting with Apps scripts.
I wrote a function that does approximately what you described. It works with the range B3:B157 of the sheet '9th grade' in the current spreadsheet. For each of them, it sets the validation rule to be: a value in the same row, columns B and C of sheet 'List Data'. The line with
....... = listData.getRange(i+3, 2, 1, 2);
will need to be modified if the source range of validation is to be different. Here, the parameters are: starting row, starting column, number of rows, number of columns. So, 2 columns starting with the second, in row numbered i+3.
function setRules() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var grade = ss.getSheetByName('9th Grade');
var listData = ss.getSheetByName('List Data');
var range = grade.getRange('B3:B157');
var rules = range.getDataValidations();
for (var i = 0; i < rules.length; i++) {
var sourceRange = listData.getRange(i+3, 2, 1, 2);
rules[i][0] = SpreadsheetApp.newDataValidation().requireValueInRange(sourceRange).build();
}
range.setDataValidations(rules);
}
I land in this issue for a diferent reason: "Just mass DataValidation copy (or update) in one column". Thanks, to user3717023 that bring me a light.
I hope that helps someone this simplification.
function setRules() {
//select spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var leads = ss.getSheetByName('Leads');
//Select correct Datavalidation
var rangeNewDataValidation = leads.getRange('M2:M2');
var rule = rangeNewDataValidation.getDataValidations();
//Copy (or Update) Datavalidation in a specific (13 or 'M') column
var newRule = rule[0][0].copy();
Logger.log(leads.getMaxRows())
for( var i=3; i <= leads.getMaxRows(); i++){
var range = leads.getRange(i, 13);
range.setDataValidations([[newRule.build()]]);
}
}

Find&Replace script in Google Docs SpreadSheets

I have google spreadsheet with direct links to images (jpg and png):
https://docs.google.com/spreadsheet/ccc?key=0AoPGWppcjtzhdDh6MW1QNVJhSHlwVTlfRnRtd0pvNGc&usp=sharing
I want to increase rows heights starting from "2nd row" to 100px and render images there.
It's possible to do via Find&Replace:
Find jpg and Replace to jpg", 1)
Find http://img and Replace to =image("http://img)
Select rows and Scale them
and the same for png image-urls.
Watch this screencast http://www.screenr.com/S0RH
Is it possible to automate it via script? I think - YES! It have to be pretty simple but I googled a lot but haven't found the solution. I can't do it myself as don't know coding. Will anyone help and make this script?
A function to do what you ask is simple, if you have a basic understanding of the language (Javascript), know how to use the development environment, and read the API documentation.
For example, see this script. It's been added to your shared spreadsheet, so you can also view it (and run it) in the script editor there.
/**
* Scan column A, looking for images that have been inserted using
* =image() function. For any row with an image, set the row height
* to 100 pixels.
*/
function resizeImageRows() {
var sheet = SpreadsheetApp.getActiveSheet(); // Get a handle on the sheet
var HEADERS = 1; // Number of header rows at top
var firstRow = HEADERS + 1; // First row with data
var lastRow = sheet.getLastRow(); // Last row with data
var imageRange = sheet.getRange(1, 1, lastRow, 1); // Column A
// Get all formulas from Column A, without Headers
var formulas = imageRange.getFormulas().slice(HEADERS);
// Look for image() formulas, and set the row height.
for (var i = 0; i< formulas.length; i++) {
if (formulas[i][0].indexOf('image') !== -1) {
sheet.setRowHeight(i+firstRow, 100); // Set height to 100 pixels
}
}
}
You can absolutely do this with the find and replace function under the edit menu, just make sure you click "search in formulas" and it will find and replace in the formula.

Google Script Image Resizing

I'm trying to make a script that will resize the images in a google doc. What I have is:
var imgs = currentDoc.getImages();
for (var i = 1; i < imgs.length; i++)
{
cell = row.insertTableCell(1);
imgNew = imgs[i].setWidth(365);
cell.insertImage(1, imgNew.getBlob());
}
The image gets inserted correctly but the size does not change regardless of what I set the width to. Since the image is going into a cell (width=370), is it possible to just make the image take up 100% of the width and scale the height proportionally? If not I can deal with manually setting the number of pixels but that is not working either. Any ideas?
The problem is that the image size should be changed after it is inserted to a table. The following code works correctly
function test() {
var doc = DocumentApp.openById('here_is_doc_id');
var imgs = doc.getImages();
var table = doc.getTables()[0];
for (var i = 0; i < imgs.length; i++) {
var row = table.appendTableRow();
var cell = row.insertTableCell(0);
var imgNew = imgs[i].copy();
cell.insertImage(0, imgNew);
imgNew.setWidth(365);
}
}
Please mention, that array indexes, cells numbers, etc. start from 0 and not 1.
Just as an FYI, you don't need to call getBlob()... anything that has a getBlob() can be passed in directly wherever a Blob is needed.
Have you tried:
imgs[i].attr('width', '370');
Or try assigning a class that has width: 100%

Resources