Office Scripts Excel - Set Transparency for bubble chart markers - javascript

I am creating a bubble chart in the online Version of MS Excel with the Automate -> Code Editor Typescript language. I am trying to set the transparency for the markers in a bubble chart but I cannot figure it out and I couldn't find any info in the Office Scripts doc. In the following code I am looping through some info / colors / dataranges in the Worksheet and I am creating data series for the bubble chart dynamically.
for (let i = 0; i < categories_count; i++) {
var row = 13;
var column = 7;
var series_name = sheet.getCell(row + i, column).getValue();
var series_range_x = sheet.getCell(row + i, column + 1).getValue();
var series_range_y = sheet.getCell(row + i, column + 2).getValue();
var series_range_z = sheet.getCell(row + i, column + 3).getValue();
var series_color = sheet.getCell(row + i, column + 4).
getFormat().getFill().getColor();
var new_series = chart.addChartSeries(series_name);
new_series.setXAxisValues(sheet.getRange(series_range_x));
new_series.setValues(sheet.getRange(series_range_y));
new_series.setBubbleSizes(sheet.getRange(series_range_z));
new_series.getFormat().getFill().setSolidColor(series_color);
}
All the methods don't seem to have a transparency attribute which I could use.
It is also strange, that I cannot set the transparency manually in the online Excel version.

You could set the Bubble chart to a certain style.
function main(workbook: ExcelScript.Workbook) {
let sheet = workbook.getWorksheet("Sheet1");
let newChart = sheet.addChart(ExcelScript.ChartType.bubble, sheet.getRange("B1:D6"))
let chartStyle = newChart.getFormat().setColorScheme(25);
}
Setting the color scheme to 25 will give you MonochromaticPalette12 (see here).
This will give you a transparent-looking light blue for the Bubbles.

Excel Online (Excel on the Web) supports a subset of features currently available in Excel Desktop.
Office Script only supports APIs that can be used in Excel Online.
If you are unable to do something (like set the transparency of a chart) in the UI in Excel Online, it's unlikely this can be done though an Office Script API.
If this feature is important for your scenario please send feedback: Automate Tab -> Code Editor -> ... -> Send Feedback

Related

How to copy and paste "Over the Cells" images using Google apps script?

I want to copy and paste the images that are 'over the cell' to another sheet. I am trying to create a dashboard where users can select the title which are written in "Alt text" of the images. And the image will appear on the dashboard which will also be over the cell. I have searched the class OverGridImage but there is no any option to copy and paste over the cell images.
We can obviously put the images in cells but that is not what I am looking for.
Any help would be appreciated. Thanks in advance.
The following image is a test of dashboard I am trying to create. The images are over the cell. Column 'H' and column 'I' are the result of script. column 'G' is list of "alt text" of images. and I want to copy and paste those images using script.
I don't think what you're trying to do is currently possible.
The class OverGridImage was released quite recently and there is no way to retrieve the Blob for such images. There is actually an open Feature Request in Issue Tracker regarding this. Since there is no BlobSource interface related to this class, there is no way to get a reference of that image, if you have uploaded it from your device. And currently there is also no way to retrieve the image via Sheets API.
Theoretically, if you add the image via URL, it would be possible to get the URL via getUrl() and insert it to the sheet via insertImage(url, column, row), but getUrl doesn't seem to be working reliably, at least for some images (there is an open issue in Issue Tracker to tackle this).
Workaround (of a sort):
The only thing I can think of is manually adding the URL somewhere it can be accessed (for example, in the image description), and use that URL to insert the image in the other sheet. Then, you could use a function along these lines:
function onEdit(e) {
var range = e.range;
var value = range.getValue();
var editedSheet = range.getSheet();
if (range.getA1Notation() === "G7" && editedSheet.getName() === "Destination" && value != "") {
// Remove previous images from "Destination" sheet:
var currentImages = editedSheet.getImages();
for (var i = 0; i < currentImages.length; i++) {
currentImages[i].remove();
}
// Get correct url from "Origin" sheet:
var origin = e.source.getSheetByName("Origin");
var images = origin.getImages();
var blob;
for (var j = 0; j < images.length; j++) {
if (images[j].getAltTextTitle() === value) { // Check if "Alt text" matches the dropdown value
url = images[j].getAltTextDescription(); // Get url (first added in description)
break;
}
}
// Insert new image in "Destination":
editedSheet.insertImage(url, 1, 1);
}
}
I hope this is of any help.

Extract selected data in Bokeh to text file and other questions

I am currently working on a Bokeh script that will display an earthquake catalogue on a map. So far, I have had little trouble, but I have stumbled upon a couple questions.
1) I came upon this stackoverflow Q&A: Get selected data contained within box select tool in Bokeh, which was very helpful in learning how to use CutsomJS to take the selected data and output it. I have, however encountered a bit of oddness. The script only seems to work properly for me in the Jupyter notebook. The CustomJS portion reads as follows:
source.callback = CustomJS(args=dict(p=p), code="""
var inds = cb_obj.get('selected')['1d'].indices;
var d1 = cb_obj.get('data');
console.log(d1)
var kernel = IPython.notebook.kernel;
IPython.notebook.kernel.execute("inds = " + inds);
If I try running it through and html window, the following command has no output:
subset = zip([source.data['xvals'][i] for i in inds],
[source.data['yvals'][i] for i in inds])
subset_array = np.array(subset)
outfile = 'Scripts/subset.xy'
fo = open(outfile,'w')
for i in range(len(subset_array)):
print(subset_array[i,0],subset_array[i,1],file=fo)
fo.close()
I could use some advice on how to get the selected data to output to a variable, and ultimately a text file when using html, as opposed to the Jupyter notebook.
2) I have been trying to create a legend for my plot. The earthquakes are indicated by circles (so it is a circle plot), and the circles vary in size based on their magnitude and in colour based on their depth, which I have gotten to work. What I would like to do is show circles of different sizes in the legend, each reflecting different magnitudes (Mag 1, Mag 2, Mag 3, etc.). Here's the command I use for plotting the data:
p.circle("xvals", "yvals",source=source, size="radius", fill_color=transform("depth", mapper),legend = 'Magnitude')
I've tried messing around with the legend commands, but it's all a bit difficult for me to grok, even though I feel like this should be a pretty simple thing to do.
I am utilizing the latest version of Bokeh (0.12.7) and Python 2.7.12. Thanks for any help, and I appreciate the time!
On question 1):
If you are creating your html file with Bokeh's output_file function, you cannot access any python code from it, since the resulting file is just html + javascript. The file saving functionality could be embedded in the javascript code (a bit tricky since it seems there is no solution that works in every browser). Another option would be to run a bokeh server and implement some mechanism to push the data to the client.
Below is a rough example where the file saving functionality is included in the html file. This should work on non-IE browsers.
from random import random
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.models import CustomJS, Button
from bokeh.layouts import row, column
# Create some random data and put it into a ColumnDataSource
x = [random() for x in range(100)]
y = [random() for y in range(100)]
source_data = ColumnDataSource(data=dict(x=x, y=y))
# Create a button that saves the coordinates of selected data points to a file
savebutton = Button(label="Save", button_type="success")
savebutton.callback = CustomJS(args=dict(source_data=source_data), code="""
var inds = source_data.selected['1d'].indices;
var data = source_data.data;
var out = "";
for (i = 0; i < inds.length; i++) {
out += "(" + data['x'][inds[i]] + ", " + data['y'][inds[i]] +") ";
}
var file = new Blob([out], {type: 'text/plain'});
var elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(file);
elem.download = 'selected-data.txt';
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
""")
# Plot the data and save the html file
p = figure(plot_width=400, plot_height=400, tools="lasso_select, reset")
p.circle(x='x', y='y', source=source_data)
plot = column(p, savebutton)
output_file("test.html")
show(plot)

Retrieving the output of a Google Apps script to local computer

I'm running a Google Apps Script (based on Gmail data) and I want to save some data from Javascript to local computer. How is it possible to save/download some data, computed in Javascript here:
to a local file?
All I have found is:
var addresses = [];
var threads = GmailApp.search("label:mylabel", 0, 10);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
addresses.push(messages[j].getFrom());
}
}
Logger.log(addresses);
but Logger.log(...) is not very useful to save this data to local computer.
I propose this as an other answer.
If I got data from Google Apps Script and Google Drive, I think that Web Apps can be used for the situation. For example, it retrieves data from Google as a trigger run=ok, a following sample script can be used.
Script :
function doGet(e) {
if (e.parameter.run == "ok") {
// do something
var result = "sample data"
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.TEXT);
}
return
}
You can retrieve data of result using curl on your local PC as follows. The URL is Web Apps URL.
curl -L https://script.google.com/macros/s/#####/exec?run=ok
Result :
sample data
A Google Apps Script can't save anything directly to your computer. But it can save data to a Google Spreadsheet, which you can then download.
You may want to either use an existing spreadsheet, or create a new one. So, the logic begins either with
var ss = SpreadsheetApp.create("Output"); // new spreadsheet
or
var ss = SpreadsheetApp.openByUrl(url); // existing spreadsheet
Either way, suppose you want to store the list of addresses in Column A of the first sheet in this spreadsheet. That would be
var sheet = ss.getSheets()[0];
var range = sheet.getRange(1, 1, addresses.length, 1);
var data = addresses.map(function(x) {return [x];});
range.setValues(data);
The intermediate step with data is to turn the 1-dimensional array addresses into two-dimensional one, [[addr1], [addr2], ...] - this is the way that values are represented in Google Sheets.
Last night I was having some trouble debugging a program and I wanted to be able to view the json in the new UltraEdit on my computer so this is how I got the data from my google script to my computer.
function getText(obj)
{
var presentationId=getPresentationId();
var data=Slides.Presentations.Pages.get(obj.presId, obj.pageId);
myUtilities.saveFile(data)
for (var i=0;i<data.pageElements.length;i++)
{
if(data.pageElements[i].shape && data.pageElements[i].shape.text && data.pageElements[i].shape.text.textElements.length)
{
for(var j=0;j<data.pageElements[i].shape.text.textElements.length;j++)
{
if(data.pageElements[i].shape.text.textElements[j].textRun)
{
var text=data.pageElements[i].shape.text.textElements[j].textRun.content;
}
}
}
}
return text;
}
myUtilities.saveFile(data) is part of a utilities library I wrote that makes it easy to store all kinds of data in ascii files. It just takes a few minutes and the file is auto synced down to my computers Google Drive and I opened the file with UltraEdit and begin analyzing it. Nothing remarkable. No fancy foot work just taking advantage of what's already there.

Generate a designed PDF report from a web application

I want to generate a PDF report from a web application. The PDF should contain charts (pie, bar), tables, different fonts and colors.
The server-side of the application is Java, the client-side is AngularJS (and of course CSS3 and HTML).
Two main options:
The client side will pass some parameters to the server, and the server will generate the PDF report, using a Java package. Then the report will be sent back to the client as a downloaded file.
The client will generate the report, using a JS package that converts HTML and CSS to PDF.
In the Java world, I've found for example iText and JFreeChart, like here. The problem here is that the design of charts look bad in the example, and I don't know if it can be changed to be designed by the style-guide I have (a design that can be done easily with CSS).
In the JS world, I've found for example html2canvas and pdfMake, like here. The problem here is that I'm not sure the conversion from HTML to canvas and then to PDF will work good in an Angular application. And I'm not sure it converts well complicated DOM elements, like charts in svg or canvas elements.
Do you have any experience with these packages? Do you know other recommended packages for this task, client or server?
Want to share my solution... I chose a client-side solution.
I started with jsPDF, but had some problems. For example, it was hard to convert tables with the style I want.
I chose pdfMake for the PDF generation, html2canvas for taking screenshots of complicated designed components, and canvg for conversion of d3js charts (svg charts) to canvas (pdfMake can add canvas as image to the document).
I wrote a function that gets the CSS class of the HTML root of the part I want to convert to PDF (remember it's a single-page application), and also gets a meta data of which HTML nodes (again, by their CSS classes) should be added to the PDF (and what type is the node - table/text/image/svg).
Then, with DOM traversing, I walked through the elements I want to add to the PDF, and handled each one by its type. Part of the code (the traversing and the switch-case by type):
$(htmlRootSelector).contents().each(function processNodes(index, element) {
var classMeta = getMetaByClass(element.className);
if (!classMeta) {
$(element).contents().each(processNodes);
return;
}
var pdfObj = {};
pdfObj.width = classMeta.width || angular.undefined;
pdfObj.height = classMeta.height || angular.undefined;
pdfObj.style = classMeta.style || angular.undefined;
pdfObj.pageBreak = classMeta.pageBreak || angular.undefined;
switch (classMeta.type) {
case 'text':
pdfObj.text = element.innerText;
pdfDefinition.content.push(pdfObj);
break;
case 'table':
var tableArray = [];
var headerArray = [];
var headers = $(element).find('th');
var rows = $(element).find('tr');
$.each(headers, function (i, header) {
headerArray.push({text: header.innerHTML, style: classMeta.style + '-header'});
});
tableArray.push(headerArray);
$.each(rows, function (i, row) {
var rowArray = [];
var cells = $(row).find('td');
if (cells.length) {
$.each(cells, function (j, cell) {
rowArray.push(i % 2 === 1 ? {text: cell.innerText, style: classMeta.style + '-odd-row'} : cell.innerText);
});
tableArray.push(rowArray);
}
});
pdfObj.table = {
widths: $.map(headers, function (d, i) {
return i === 0 ? 80 : '*';
}),
body: tableArray
};
pdfDefinition.content.push(pdfObj);
break;
case 'image':
html2CanvasCount++;
htmlToCanvas(element, pdfObj);
pdfDefinition.content.push(pdfObj);
break;
case 'svg':
svgToCanvas(element, pdfObj);
pdfDefinition.content.push(pdfObj);
break;
default:
break;
}
$(element).contents().each(processNodes);
});
This is the solution in general.
Hope it will help someone.

Can mxGraph export graphs as PDFs?

I am working on a project that uses mxGraph where I am required to export a high resolution output in PDF for a service process diagram. I've tried recreating the graph using JGraphX, the Java Swing client and exporting that to a PDF, but the result is not close to what the browser displays.
There's no PDF export in JavaScript on the client, does mxGraph have any explicit support for PDF generation from JavaScript?
I'll explain the case of a client initiated request, where the diagram is displayed on the browser when the request is made. This is the standard case, mxGraph transmits an XML representation of the graph using custom graphics primitives and these are received on the server and decoded either by the Java or .NET back-ends.
The reason for the need for the graph being displayed is there are certain text measurements that are hard to recreate outside of a browser environment.
On the client side you need to create the required immediate XML using, say, the diagrameditor.html example as a guide:
var exportImage = function(editor)
{
var graph = editor.graph;
var scale = graph.view.scale;
var bounds = graph.getGraphBounds();
// New image export
var xmlDoc = mxUtils.createXmlDocument();
var root = xmlDoc.createElement('output');
xmlDoc.appendChild(root);
// Renders graph. Offset will be multiplied with state's scale when painting state.
var xmlCanvas = new mxXmlCanvas2D(root);
xmlCanvas.translate(Math.floor(1 / scale - bounds.x), Math.floor(1 / scale - bounds.y));
xmlCanvas.scale(scale);
var imgExport = new mxImageExport();
imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas);
// Puts request data together
var w = Math.ceil(bounds.width * scale + 2);
var h = Math.ceil(bounds.height * scale + 2);
var xml = mxUtils.getXml(root);
// Requests image if request is valid
if (w > 0 && h > 0)
{
var name = 'export.png';
var format = 'png';
var bg = '&bg=#FFFFFF';
new mxXmlRequest(editor.urlImage, 'filename=' + name + '&format=' + format +
bg + '&w=' + w + '&h=' + h + '&xml=' + encodeURIComponent(xml)).
simulate(document, '_blank');
}
};
Where editor.urlImage is the URL of the image generating servlet, in the case for a Java back-end.
On the server-side, in the case of Java, look at the java/examples/com/mxgraph/examples/web/ExportServlet.java. That looks at the "format" parameter passed up, and if 'pdf', the writePdf() method is invoked.
That method creates an PdfWriter and renders the graphics primitives to a Java Swing Graphics2D using the Java favoured part of mxGraph.
This example writes the PDF result directly to the outstream of the servlet repsonse in this line:
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
You could map the output to any stream.
Note that you need to setup iText to map every font you need in the PDF. This isn't always ideal for a large number of fonts. It's worth testing a few cases of the export to see if the output is good enough for your requirements. We're currently researching the use of PhantomJS for the export. If the Java export isn't good enough, please post another question regarding using PhantomJS and I'll detail the process for that.
iText is provided as an example PDF library to use, it's easier since it's under an open source library. It's possibly not the best suited library, we didn't find it easy to work with for this specific scenario. You might also want to investigate other Java PDF generation libraries.
Also note that the .NET back-end only supports raster image generation in dotnet/aspnet/Export.ashx, there's no known open source PDF library to supply as an example there.
Full vector solution:
Set mxClient.NO_FO = true;
Export SVG to PDF by svg2pdf.js
Write all DIV's text to pdf by jsPDF
Example:
let pdf = new jsPDF('p', 'pt', 'a4', false, false);
mxClient.NO_FO = true;
let graph = Draw(drawdiv, false);
let svgEl = drawdiv.children[1];
//draw svg:
svg2pdf(svgEl, pdf, {
xOffset: pdfPageDefaultOffsetX,
yOffset: pdfOffsetY,
scale: divToPdfRatio
});
//draw text:
for (let child of drawdiv.children) {
if (child.tagName === 'DIV') {
let splitText = pdf.splitTextToSize(child.innerText, Math.ceil((childSizes.width) * divToPdfRatio));
pdf.text(pdfPageDefaultOffsetX + (child.offsetLeft * divToPdfRatio), textPositionTop, splitText, {
align: child.style.textAlign,
lineHeightFactor: 1,
});
}
}
pdf.save('Test.pdf');

Categories