Creating an app script function that generates a chart object for any google sheet - charts

I am trying to create a function in app scripts that generates a chart whenever I pass in the data labels and data points into the function as so:
makePiChart(LabelRange,DataRange)
labelRange: January,February,March....
DataRange: 5,4,3,.......
However, when I try clicking on a cell and typing in the function with the range arguments I get an error.
I first was trying to test if I could get the chart output for a single sheet.
This is the code I have for that.
function makePiChart() {
var ss = SpreadsheetApp.openById("#Id for Spreadsheet")
SpreadsheetApp.setActiveSpreadsheet(ss)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("January");
sheet1.activate()
var chart = sheet1.newChart()
.setChartType(Charts.ChartType.PIE)
.addRange(sheet1.getRange("C4:C11"))
.addRange(sheet1.getRange("H4:H11"))
.setPosition(5,5,0,0)
.setOption("Issues","Dynamic Chart")
.build();
return sheet1.insertChart(chart);
}
Now this generates the chart for the January sheet as I expect.
However, I want to create a function that generalizes this process. So if I go to some sheet in spreadsheet, say I had a Spreadsheet for the entire year and I go to the January sheet, February Sheet, March Sheet etc. and if I click on a cell and type
makePiChart(Rangeforlabels,RangeforData)
I'll get a piechart object that is made using only those data ranges.
Basically, I dont want to keep modifying scripts to generate chart objects. I want to be able to type in =makePie(labelRange,DataRange) into any cell and have a chart object appear. Its location does not matter.

Related

How to add data table in chart from office script

I create the online chart from my pivot table.that pivot table is source my chart.but i can't get chart data table in office script
I need to add "chart data table" from office script code
Here is my code. I don't have any idea how to add that data table in chart.
// Insert pivot chart on sheet sheet1
let chart_1 = sheet1.addChart(ExcelScript.ChartType.columnClustered, newPivotTable.getLayout().getRange());
// Resize and move chart chart_1
chart_1.setLeft(543.75);
chart_1.setTop(24.75);
chart_1.setWidth(360);
chart_1.setHeight(216);
// Resize and move chart chart_1
chart_1.setLeft(543.75);
chart_1.setTop(24.75);
chart_1.setWidth(468);
chart_1.setHeight(273);
// Change major gridlines visibility for chart chart_1
chart_1.getAxes().getValueAxis().getMajorGridlines().setVisible(false);
// Change minor gridlines visibility for chart chart_1
chart_1.getAxes().getValueAxis().getMinorGridlines().setVisible(false);
// Change title text for chart chart_1
chart_1.getTitle().setText("Active HC");
If you're asking about how to create a chart from a data table you can use most of the code you have above. You just have to reference the range of the data table e.g. in a variable. And then use that variable when you add the chart. So you could use your code in your initial post but edit it like so:
let dataTbl = sheet1.getRange("data_table_range here") //you will need to change the sheet if the dataTable is not located on Sheet1
let chart_1 = sheet1.addChart(ExcelScript.ChartType.columnClustered, dataTbl); //you will need to change the sheet if you don't want the chart to appear on Sheet1

Auto select an option from a dropdown after a certain date

I'm creating a lost&found log for work, I have a dropdown list with options like "Collected", "Sent to guest", "Donated" etc.
I'd like to have the sheet automatically select 'Donated' after a certain date (maybe after 1 month) IF an option hasn't already been selected.
E.G. If somebody inputs a found pair of gloves on Nov 2nd, The empty dropdown will automatically change to 'Donated' on Dec 2nd unless somebody already selected another option (E.G. 'Collected').
You can accomplish this by either making use of Apps Script to check the conditions and make the corresponding changes or by directly implementing Sheets functions.
Sheets Functions
You can achieve the desired outcome by putting this formula on each status cell:
=IF(TODAY()-D4>30,"Donated","")
It will work as intended, the cell will not display anything until there are 30 days between the TODAY() date and the date provided in the D4 cell. If there are, the cell will display Donated. If another option from the drop-down is selected, that will erase the formula and only the new value will be displayed.
However, this method is more of a quick hack than an actual robust solution, as several things can go wrong. For instance, if an option from the drop-down is chosen by accident and then it is left blank again, the method will not work anymore for that line as the formula will have been permanently erased.
You can read about how TODAY() works here.
Apps Script (recommended)
The following script will check that, for every row in the sheet, both the status cell is blank and that subtracting the DATE FOUND is more than 30 days (unfortunately that has to be done in milliseconds).
function myFunction() {
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadSheet.getSheetByName("Sheet1");
sheet.getLastRow()
var range = sheet.getRange(4,1,sheet.getLastRow(), 7);
//SELECT A RANGE WITH THE 7TH FIRST COLUMNS AND AS MANY ROWS AS NECESSARY
//(WE ARE INTERESTED IN DATA STARTING FROM ROW 4TH)
var values = range.getValues();
var millisecondsIn30Days = 30 * 24 * 60 * 60 * 1000;
for(var row = 0; row<values.length; row++){
var status = values[row][6]; //STATUS IS THE 6TH ELEMENT IN THE ROW ARRAY (COLUMN G)
if(status == "" && (new Date() - values[row][3]) > millisecondsIn30Days){
//MORE THAN 30 DAYS AFTER FOUND
sheet.getRange(row+4,7).setValue("DONATED");
}
}
}
Of course, that script can be run manually or the job can be automated with an installable trigger that runs, for example, every month. You can read more about how to set up such triggers here.

LibreOffice BASIC function - Copy if over a value to a new sheet

I'm trying to create a simple function on a LibreOffice Calc sheet.
I have a table of information where cells A1:K2 has headings (the cells in Row 2 are merged)
all the information runs from A3:K176
The sheet has various functions running on it already, all I need is one more function.
At first I wanted it to automate when i open, but then i thought running the BASIC macro off of a button might be better, so i can edit and then just hit the button once I'm done.
I have the button linked up to run the macro already, but now im stuck... I have tried many ways of writing the code, but it seems that i am just too green to figure it out.
the last time i ran Excel advanced functions i was in high school.
ok, enough talking...
All I need the macro to do is once I hit the button, I need it to check column K and any value > 1 it needs to take that whole row and copy it then go to a target sheet, clear any data on the target sheet. then copy that set of rows to the next open row in the target sheet. possibly even exporting the result to a .txt file as a bonus.
this is a start...
in future I would like to add another button that will do the same function to a array lower down and put that into a different sheet.
Option Compatible
Sub SWD_AwakeningsTrade
Dim i, LastRow
LastRow = Sheets("Card_List").Range("A" & Rows.Count).End(xlUp).Row
Sheets("Awakenings For trade").range("A2:I500").clearContents
For i=2 to LastRow
If Sheets("Card_List").Cells(i,"K").Value = "(>1)" Then
Sheets("Card_List").Cells(i, "K").EntireRow.Copy
Destination:=Sheets("Awakenings For trade").Range("A" & Rows.Count.end(xlUp)
End if
next i
End Sub

Excel stops working when adding new row to the Table

I don't know why but when I try to do this Excel Quits without saving anything:
On Sheet1 I have 11 Rows x 6 cols formatted as Table. With 1st row as Table Header.
I assign col A as a STU_ID Named Range using Name Manager.
I have only a listbox on the Userform. And I give RowSource property as =STU_ID . I get the col A data on the list box.
Now when I go to Sheet1 and try to add more data on next row of the table. Excel quits saying it has stopped working. Windows is checking for error and it restarts on a blank Workbook.
Shouldn't Listbox be dynamic and get data from Name Manager as I add them on the sheet ?
I am using MS Excel Pro 13 on Win 10 64 bit.
This is a bug in Excel. As a workaround, use the .List property instead of the .RowSource.
Try something like this in the UserForm's code:
Private Sub UserForm_Initialize()
ListBox1.List = Range("table1[abc]").Value
End Sub
This way it will be dynamic, and it will work.
If you need it to change while the userform is displayed, put a small code to the Sheet change event, that updates the list every time the sheet changes. (This is only necessary if your form is modal, and you want it to reflect the changes made in real-time.)

JavaFX chart: proper way to switch series data

We have a java program that takes a CSV file and processes it into multiple sets of data. The data is displayed one at a time on an XYChart with a ComboBox to choose between them. However we keep running into problems updating / changing the data:
First we had a bunch of ObservableList objects for each data series, e.g.
ObservableList<XYChart.Data<T,V>> data = FXCollections.observableArrayList();
and whenever the ChoiceBox selection was changed we would clear the series and add the one corresponding to the different selection, e.g.
theChart.getData().clear();
theChart.getData().add(new XYChart.Series<T,V>(data));
However, we would get errors when data was updated saying something about same data added to multiple charts. I think this would occur if theChart.getData().add(new XYChart.Series<T,V>(data)); had been called twice for the same data beforehand.
So I wrapped it up like
XYChart.Series<T,V> series = new XYChart.Series<>(data);
and changed the chart data like:
theChart.getData().clear();
theChart.getData().add(series);
Works fine on my computer but on another when data is cleared and then added to we get a null pointer exception during the series onChanged event, which suggests some kind of race condition.
Questions:
What is the proper what to change the series that a JavaFX chart is displaying?
Is there a way to 'pause' onChanged events so that an entire data series can be updated before the chart tries to redraw.
You can't do a clear(), that will throw an UnsupportedOperationException. The proper way to update the chart is setting a new empty ObservableList and then add the new XYChart.Series with the proper XYChart.Data objects into.
chart.setData(FXCollections.observableArrayList());
XYChart.Series<T, V> series = new XYChart.Series<T, V>();
XYChart.Data<T, V> data = new XYChart.Data<T, V>(t_type_Value, v_type_Value);
series.getData().add(data);
chart.getData().add(series);