Is it possible to convert a Chart to and EmbeddedChart? - google-apps-script

I'm attempting to Create a few charts out of a Sheet of data, but the charts are grabbing sort of specific data so I have found it advantageous to use the DataTableBuilder class. I am able to specify labels for the data more easily than I can from the original sheet. However, I cannot embed a Chart Class into a Sheet. Is it possible to either convert a Chart to an EmbeddedChart or use a DataTable to create an EmbeddedChart?I'm attempting to Create a few charts out of a Sheet of data, but the charts are grabbing sort of specific data so I have found it advantageous to use the DataTableBuilder class. I am able to specify labels for the data more easily than I can from the original sheet. However, I cannot embed a Chart Class into a Sheet. Is it possible to either convert a Chart to an EmbeddedChart or use a DataTable to create an EmbeddedChart?
This is the data below, and I need only the last column (5/11) and I don't need the total row. So its not a concise range, else I would just use the Embedded chart builder.
May 5/1 5/2 5/3 5/11
Critical 0 0 0 0
High 0 0 0 0
Call Immediate 4 11 4 3
Daytime Call 3 3 6 1
Totals 7 14 10 4
Below is the how I've built the Chart in which dailyTotals is a range of [0, 0, 3, 1]. This works fine, but I can't label anything.
var dailyChart = LOB.newChart()
.setChartType(Charts.ChartType.BAR)
.setOption('title', LOB.getName())
.addRange(dailyTotals)
.build();
LOB.insertChart(dailyChart);
Below is building the DataTable, this time daily totals is just an array. But this gives me labels.
dailyTable = Charts.newDataTable()
.addColumn(Charts.ColumnType.STRING, "Priority")
.addColumn(Charts.ColumnType.NUMBER, "Incidents")
.addRow('P1', dailyTotals[0])
.addRow('P2', dailyTotals[1])
.addRow('P3', dailyTotals[2])
.addRow('P4', dailyTotals[3])
.build();
How can I either use a DataTable to create an EmbeddedChart? or how can I turn a Chart into and Embedded chart?

I actually figured out a solution that worked for me before I got a response from anyone. It involves using a legend to determine which bar is which, rather than labels along the x-axis, but it totally covers my requirements and might help out some one else out.
var dailySeries = {
0:{color: 'blue', labelInLegend: 'P1'},
1:{color: 'red', labelInLegend: 'P2'},
2:{color: 'yellow', labelInLegend: 'P3'},
3:{color: 'green', labelInLegend: 'P4'}
}
var dailyChart = LOB.newChart()
.setPosition(8, 27, 0, 0)
.setChartType(Charts.ChartType.BAR)
.asColumnChart()
.setOption('title', LOB.getName())
.addRange(dailyTotals.getCell(1, 1))
.addRange(dailyTotals.getCell(2, 1))
.addRange(dailyTotals.getCell(3, 1))
.addRange(dailyTotals.getCell(4, 1))
.setOption('series', dailySeries)
.build();
LOB.insertChart(dailyChart);

You would need to re-create the below range somewhere else in the sheet and add that as range instead.
A B
P1 0
P2 0
P3 3
P4 1
The range [P1, P2, P3, P4] can also be somewhere else. Then you can add both ranges:
.addRange([P1 to P4 range])
.addRange(dailyTotals)
.setOption('useFirstColumnAsDomain','true')

Related

How do I get a multiple-line subtitle in google sheet charts?

I am creating a bar chart in google sheet, recording it with a macro, and running the code for different data cases.
When the subtitle is too long, there is missing text on the chart, shown with ellipses (...)
Increasing the chart's width reveals more of the text but not all.
Increasing the chart's height does nothing! (It reveals a long title, but not a long subtitle!)
Adding a line break doesn't work. When using one, all I can see is the first line of the subtitle, while the others stay completely hidden...
How can I have a subtitle that shows all of the text I want to display?
Given that titles are responsive in both the horizontal and vertical axes, it's really odd for subtitles not to be.
Thank you
---- Edit ----
The script helps automate things, but I don't think that it adds new functionalities. That being said, the code I use is the following:
function Macro3() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var chart = sheet.newChart()
.asBarChart()
.addRange(spreadsheet.getActiveRange())
.setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS)
.setTransposeRowsAndColumns(false)
.setNumHeaders(4)
.setHiddenDimensionStrategy(Charts.ChartHiddenDimensionStrategy.IGNORE_BOTH)
.setOption('bubble.stroke', '#000000')
.setOption('useFirstColumnAsDomain', true)
.setOption('isStacked', 'false')
.setOption('su', SpreadsheetApp.getActiveSheebtitlet().getRange("B2:B2").getValue())
.setOption('title', SpreadsheetApp.getActiveSheet().getRange("B1:B1").getValue())
.setOption('annotations.domain.textStyle.color', '#808080')
.setOption('textStyle.color', '#000000')
.setOption('legend.textStyle.color', '#1a1a1a')
.setOption('subtitleTextStyle.color', '#999999')
.setOption('titleTextStyle.color', '#757575')
.setOption('annotations.total.textStyle.color', '#808080')
.setXAxisTitle(SpreadsheetApp.getActiveSheet().getRange("B4:B4").getValue())
.setOption('hAxis.textStyle.color', '#000000')
.setYAxisTitle(SpreadsheetApp.getActiveSheet().getRange("A4:A4").getValue())
.setOption('vAxes.0.textStyle.color', '#000000')
.setPosition(2, 1, 30, 0)
.build();
sheet.insertChart(chart);
};
I wanted to include a screenshot of the Google sheet this macro is used upon, but this is my 1st post on stackoverflow and apparently I need at least 10 reputation to post images.
If you think it would help to share this screenshot and there is a neat way of doing it, please let me know.
Thanks again
In the current state it is not possible to add multiple lines to the subtitles of Google Sheets charts. Therefore I recommend you to go to Help > Help Sheets to Improve and add this request. Alternatively, you can use this template to request this functionality for Apps Script, for example, allowing EmbeddedCharts to have titles written with HTMLService.
Possible workarounds:
Change the font size according to the string length.
As I told you in the comments, you can measure the amount of words your subtitle has and according to that, apply different font sizes. For example:
function calcFontSize(subtitle){
const lenS = subtitle.split(" ").length
if(lenS > 12) return 8
if(len <= 12) return 12
}
// Inside your macro
.setOption(
'subtitleTextStyle.fontSize',
calcFontSize(sheet.getRange('B2:B2').getValue())
)
PROS : You have a "responsive" subtitle.
CONS: As you say In long texts ... The text becomes too small to read
Use Charts Service to create your chart
As this service allows you to add jump lines to your title, you can achieve what you want:
function createGoogleChart() {
// extracted from here https://developers.google.com/apps-script/reference/charts/charts
const data = Charts.newDataTable()
.addColumn(Charts.ColumnType.STRING, 'Month')
.addColumn(Charts.ColumnType.NUMBER, 'In Store')
.addColumn(Charts.ColumnType.NUMBER, 'Online')
.addRow(['January', 10, 1])
.addRow(['February', 12, 1])
.addRow(['March', 20, 2])
.addRow(['April', 25, 3])
.addRow(['May', 30, 4])
.build();
const chart = Charts.newAreaChart()
.setDataTable(data)
.setStacked()
.setRange(0, 40)
.setTitle("My title\nMy long long long long long \n long long long long \n subtitle")
.build();
SpreadsheetApp.getActiveSheet().insertImage(
chart.getAs('image/png'), 10, 10
)
}
PROS : You can achieve what you need.
CONS:
You insert a still image (not editable)
There is no default subtitle option
You have to build it from Apps Script, and adapt it to your macro

Using 2 different outputs of 'return' of a function in separate elements of a plot

I am drawing a plot of voltage per time. For the voltage values, I want the values to be evaluated by a 'scaling' function which converts the values from volts to kilovolts if the biggest element is higher than 1000 volts (11000 volts to 11 KILOvolts).
This function is supposed to return 2 separate outputs; one for (new) values of voltage and one for the unit. The values are fed into the y axis values of the plot and the unit is given to the labeling line of that axis. For example:
import numpy as np
time = np.array([0, 1, 2, 3])
system_voltage1 = np.array([110, 120, 130, 150])
system_voltage2 = np.array([11000, 12000, 13000, 15000])
scaling_function(input)
if np.amax(input) < 1000:
output = input/1
Voltage_label = 'Voltage in Volts'
if np.amax(input) > 1000:
output = input/1000
Voltage_label = 'Voltage in KILOVolts'
return(output, Voltage_label)
fig14 = plt.figure(figsize=(16,9))
ax1 = fig14.add_subplot(111)
l1, = ax1.plot(time, scaling_function(system_voltage), color='r')
ax1.set_xlabel("time in second", color='k')
ax1.set_ylabel(Voltage_label, color='k')
Now, I am having trouble, calling this function properly. I need the function to only receive the output for scaling_function(system_voltage), and receive Voltage_label in ax1.set_ylabel(Voltage_label, color='k'). Now:
A) My problem: I don't know how to write the code so only the first output is received and used for scaling_function(system_voltage) , and the second element for the labeling line.
B) Something I tried but didn't work:Voltage_label does not recognize the value of voltage_label from scaling_function, as it is located in an outer loop than the function. I mean, I cannot access voltage_label as its value is not globally assigned.
Can anyone help me with this?
y,l = scaling_function(system_voltage)
l1, = ax1.plot(time, y, color='r')
ax1.set_xlabel("time in second", color='k')
ax1.set_ylabel(l, color='k')

SSRS Pie chart hide 0 Value

SQL Server 2012 - SSRS Questions
I currently have a Pie chart that shows the number of deliveries as a percentage on whether they are late, on time or early. What I am trying to do is use an Expression in the Chart Series Labels "Visible" property to hide the label if it is 0 on the chat. Of note in the table this value is returned as 0.00 I have tried using various SWITCH and IFF Statements to do this but nothing seems to work and its likely I am getting the syntax wrong, can anyone help?
Table Values
TotalIssued Early Late OnTime EarlyPerc LatePerc OnTimePerc
6, 0, 4, 2, 0.00, 66.67, 33.33,
=SWITCH(
(First(Fields!EarlyPerc.Value, "EstimatesIssued") = 0),false,
(First(Fields!LatePerc.Value, "EstimatesIssued") = 0),false,
(First(Fields!OnTimePerc.Value, "EstimatesIssued") = 0),false,
true)
Thanks
Try:
=SWITCH(
First(Fields!EarlyPerc.Value, "EstimatesIssued") = 0,false,
First(Fields!LatePerc.Value, "EstimatesIssued") = 0,false,
First(Fields!OnTimePerc.Value, "EstimatesIssued") = 0,false,
true,true)
UPDATE:
If you have one field per percentage and your dataset returns one row always, you have to select each serie in the ChartData window and press F4 to see properties window.
In properties window set for EarlyPerc Visible property:
=IIF(Fields!EarlyPerc.Value=0,False,True)
And so on for the next two series you have (LatePerc and OnTimePerc).
Let me know if this helps.

Customising Google Bar Chart Using Google App Script

I am currently having some issues configuring a simple graph using Google App Scripts. I seem to be unable to find the correct documentation in order to progress any further!
I have everything hooked up pulling data from a couple of spreadsheets, so that aspect is fine!
I see that there are various ways in order to customise the looks of a chart and there are tools available for example:
http://imagecharteditor.appspot.com/
http://code.google.com/apis/ajax/playground/?type=visualization
I wish to add colours to my bar charts like in this example
http://code.google.com/apis/ajax/playground/?type=visualization#image_multicolor_bar_chart
Additionally in the first link there are options to create sections using the range marker tool. I was hoping that with these tools I could copy the code across to use in my App Script Chart.
The only way I can see this working is using .setOption(string, object)
I've tried this...
var data = Charts.newDataTable()
.addColumn(Charts.ColumnType.STRING, 'Month')
.addColumn(Charts.ColumnType.NUMBER, 'Mark Achieved')
for(var x=0; x < ChartData.length;x++){
data.addRow(ChartData[x]);
}
data.build();
var chart = Charts.newColumnChart()
.setDataTable(data)
.setDimensions(1000, 600)
.setRange(0, 100)
.setTitle('Test Scores')
.setLegendPosition(Charts.Position.BOTTOM)
.setOption('options',{cht: 'bvs', chco: 'A2C180,3D7930', max: 100})
.build();
app.add(chart);
any help would be much appreciated!
EDIT
The options you are trying to use are applicable to the static image charts (which are now deprecated), and won't work with ColumnCharts. ColumnCharts color the bars by series, not by data point, so if you want multi-colored bars, you have to separate them out into different data series. I wrote a hack that does this (see on jsfiddle for the standard javascript version). My reading of the AppsScript implementation of the Visualization API seems to preclude using calculated columns in the DataViews, but it is possible that the documentation is incomplete here. Try creating a view like this:
// add one calculated column for each month
var dataViewDefinition = Charts.newDataViewDefinition().setColumns([0, {
type: Charts.ColumnType.NUMBER,
label: 'Mark Achieved',
calc: function (dt, row) {
if (dt.getValue(row, 0) == 'January') ? dt.getValue(row, 1) : null;
}
}, {
type: Charts.ColumnType.NUMBER,
label: 'Mark Achieved',
calc: function (dt, row) {
if (dt.getValue(row, 0) == 'February') ? dt.getValue(row, 1) : null;
}
}/*...*/]);
It is probable that this needs to be tweaked, and possible that it won't work at all, in which case you would have to either change the query of the spreadsheet or rearrange the structure of the spreadsheet.
As far as adding the ranges to the chart, can you elaborate more on what you would like those to look like?

How to get cfspreadsheet to render html

I'm trying to create an excel file with cfspreadsheet. In one of the columns I have html code, but for some reason, in the excel file the html doesn't get rendered it's just plain text. eg. <b>blabla</b> instead of being bolded.
Do you know any solutions to this?
The reason is that cfspreadsheet is based on POI which does not support html content.
As user1450455 mentions, you can format whole cells using any of the built in formatting functions such as SpreadsheetFormatCell.
sheet = spreadSheetNew();
spreadSheetFormatCell( sheet, {bold=true} , 1, 1 );
spreadSheetSetCellValue( sheet, "blablah", 1, 1 );
If you are looking to create cells with multiple formats (ie bold some characters but not others) that is only possible using the underlying POI library by creating a RichTextString. So it requires much lower level code.
<cfscript>
sheet = spreadSheetNew();
workbook = sheet.getWorkBook();
helper = workbook.getCreationHelper();
richText = helper.createRichTextString("ColdFusion");
// make first few characters bold ie "Cold"
firstFont = workbook.createFont();
firstFont.setBoldweight( firstFont.BOLDWEIGHT_BOLD );
richText.applyFont( 0, 4, firstFont );
// make next characters red ie "Fusion"
secondFont = workbook.createFont();
secondFont.setColor( secondFont.COLOR_RED );
richText.applyFont( 4, 10, secondFont );
// create cell via CF and apply formats
// note, in POI indexes are base 0
spreadSheetSetCellValue( sheet, "", 2, 1);
cellA2 = workbook.getSheetAt(0).getRow(1).getCell(0);
cellA2.setCellValue( richText );
</cfscript>
You can use the spreadsheet formatting functions like SpreadsheetFormatRow or SpreadsheetFormatrows or SpreadsheetFormatColumns.