I'm looking for a REST API for generating PowerPoint slides... does anyone have any suggestions?
Realize this wouldn't be too difficult to implement, but we're trying to avoid building noncore functionality we could get from a third party.
Basically, we want to send a JSON blob and get back the generated slide.
Think this is a related question:
Is there an API to make a MS Office 365 Powerpoint presentation programmatically?
Thanks for your help!
You can try using Aspose.Slides Cloud for your purposes. This product provides REST-based APIs for many programming languages (C#, Java, PHP, Ruby, Python, Node.js, C++, Go, Perl, Swift), platforms and environments. With this product, you can use both Aspose file storages and third-party storages. Docker containers can also be used for working with Aspose.Slides Cloud.
This product does not support adding contents to presentations from JSON files but it provides many features for generating contents. It also provides features to add contents to presentations from HTML and PDF documents. The following Python sample code shows you how to add a WordArt object to a new presentation, for example.
import asposeslidescloud
from asposeslidescloud.apis.slides_api import SlidesApi
from asposeslidescloud.models.slide_export_format import SlideExportFormat
from asposeslidescloud.models.shape import Shape
from asposeslidescloud.models.fill_format import FillFormat
from asposeslidescloud.models.line_format import LineFormat
from asposeslidescloud.models.text_frame_format import TextFrameFormat
from asposeslidescloud.models.three_d_format import ThreeDFormat
from asposeslidescloud.models.shape_bevel import ShapeBevel
from asposeslidescloud.models.light_rig import LightRig
from asposeslidescloud.models.camera import Camera
slides_api = SlidesApi(None, "my_client_id", "my_client_secret")
file_name = "example.pptx"
slide_index = 1
dto = Shape()
dto.shape_type = "Rectangle"
dto.x = 100
dto.y = 100
dto.height = 100
dto.width = 200
dto.text = "Sample text"
dto.fill_format = FillFormat()
dto.fill_format.type = "NoFill"
dto.line_format = LineFormat()
dto.line_format.fill_format = FillFormat()
dto.line_format.fill_format.type = "NoFill"
text_frame_format = TextFrameFormat()
text_frame_format.transform = "ArchUpPour"
three_d_format = ThreeDFormat()
bevel_bottom = ShapeBevel()
bevel_bottom.bevel_type = "Circle"
bevel_bottom.height = 3.5
bevel_bottom.width = 3.5
three_d_format.bevel_bottom = bevel_bottom
bevel_top = ShapeBevel()
bevel_top.bevel_type = "Circle"
bevel_top.height = 4
bevel_top.width = 4
three_d_format.bevel_top = bevel_top
three_d_format.extrusion_color = "#FF008000"
three_d_format.extrusion_height = 6
three_d_format.contour_color = "#FF25353D"
three_d_format.contour_width = 1.5
three_d_format.depth = 3
three_d_format.material = "Plastic"
light_rig = LightRig()
light_rig.light_type = "Balanced"
light_rig.direction = "Top"
light_rig.x_rotation = 0
light_rig.y_rotation = 0
light_rig.z_rotation = 40
three_d_format.light_rig = light_rig
camera = Camera()
camera.camera_type = "PerspectiveContrastingRightFacing"
three_d_format.camera = camera
text_frame_format.three_d_format = three_d_format
dto.text_frame_format = text_frame_format
# Create the WordArt object and download the presentation.
slides_api.create_presentation(file_name)
slides_api.create_shape(file_name, slide_index, dto)
file_path = slides_api.download_file(file_name)
The WordArt object in the output presentation:
This is a paid product but you can make 150 free API calls per month for API learning and presentation processing.
I work as a Support Developer at Aspose.
Related
I have a bunch of Flex pages I need to convert to get rid of the flash player and have been unable to see how to replicate this code just using the javascript.
The Flex code gathers up data and sends it in a POST to a Cold Fusion page in another frame (named FrameData). Cold Fusion accesses the data from a FORM variable (FORM.mydata1, FORM.mydata2, etc.).
var RequestSite:URLRequest;
OutputPageValues.OutputType = 5;
OutputPageValues.mydata1 = "2";
OutputPageValues.mydata2 = "test";
RequestSite = new URLRequest("pageurl.cfm"));
RequestSite.data = OutputPageValues;
RequestSite.method = URLRequestMethod.POST;
navigateToURL(RequestSite, 'FrameData');
How do I emulate this construct in Royale? Is there another way to do this?
equivalente code for URLRequest:
var u:URLRequest = new URLRequest("http://domain.foo");
navigateToURL(u,"_blank");
in Apache Royale is BrowserWindow:
import org.apache.royale.core.BrowserWindow;
var u:String = "http://domain.foo";
BrowserWindow.open(u, "_blank");
To pass variables you need to do via GETmethod: "http://domain.foo?variable=" + key.
To use POST method use HTTPService class from Network SWC instead:
import org.apache.royale.net.HTTPConstants;
import org.apache.royale.net.HTTPService;
import org.apache.royale.net.URLVariables;
// add the variables to send
var urlVars:URLVariables = new URLVariables();
urlVars.set("variable", key);
// create the httpservice instance
var service:HTTPService = new HTTPService();
service.url = "http://domain.foo";
service.method = HTTPConstants.POST;
service.addEventListener("complete", resultCallback);
service.addEventListener("ioError", faultCallback);
// add the variables
service.contentData = urlVars;
// trigger the service
service.send();
Optionally in case you need to deal with CORS you can add CORSCredentialsBead bead to the HTTPService:
service.addBead(new CORSCredentialsBead(true));
(Note: code is untested, please report if all is ok so we can improve this response and code snippet, thanks)
I am trying to consume an external REST service. Example:
DATA : lo_client TYPE REF TO if_http_client.
cl_http_client=>create_by_url(
EXPORTING
url = 'http://my_url'
IMPORTING
client = lo_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
DATA(rest_client) = NEW CL_REST_HTTP_CLIENT( lo_client ).
rest_client->GET( ).
GET, POST, PUT and DELETE are Ok since they are implemented in the class CL_REST_HTTP_CLIENT.
Did anyone find a solution to use the PATCH method or how could I consume it otherwise?
PS: the constant for PATCH exists (if_rest_message=>gc_method_patch), but as I said, it's not implemented (send_receive).
Thank you.
You can use CL_HTTP_CLIENT to set method freely, CL_REST_HTTP_CLIENT is also using this class under the hood.
DATA : lo_client TYPE REF TO if_http_client.
cl_http_client=>create_by_url(
EXPORTING
url = 'http://my_url'
IMPORTING
client = lo_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
lo_client->request->set_method( 'PATCH' ).
lo_client->request->set_content_type( 'application/json' ).
lo_client->send( ).
lo_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4 ).
It's not supported indeed. Quick and dirty way to get it to work is to copy the class and add the following method:
method PATCH.
send_receive( iv_http_method = if_rest_message=>gc_method_patch io_entity = io_entity ).
endmethod.
I have the following python script (reduced, but the rest of it performs similar actions):
from Spotfire.Dxp.Application.Visuals import *
from Spotfire.Dxp.Data import *
#assign default values for prompts if needed
if Document.Properties['cannedKPISelected'].isspace():
Document.Properties['cannedKPISelected'] = 'GS'
if Document.Properties['cannedTimeSelected'].isspace():
Document.Properties['cannedTimeSelected'] = 'Month'
#determine which type of viz needs displayed based on a flag in the data
tableName='PrimaryDataTable'
columnToFetch='displayPercentageFlag'
activeTable=Document.Data.Tables[tableName]
rowCount = activeTable.RowCount
rowsToInclude = IndexSet(rowCount,True)
cursor1 = DataValueCursor.CreateFormatted(activeTable.Columns[columnToFetch])
for row in activeTable.GetRows(rowsToInclude,cursor1):
rowIndex = row.Index
percentageNeeded = cursor1.CurrentValue
break
#create consumer report
for page in Document.Pages:
for viz in page.Visuals:
if str(viz.Id) == 'a7f5b4ec-f545-4d5f-a967-adec4c9fec79':
if Document.Properties['coffeeReportSelected'] == 'Brand Category by Market':
if Document.Properties['cannedKPISelected'] == 'GS' and Document.Properties['cannedTimeSelected'] == 'Month' and percentageNeeded == 'Y':
visualContentObject = viz.As[VisualContent]()
visualContentObject.MeasureAxis.Expression = 'Sum([GS Month]) as [GS Mnth]'
visualContentObject.RowAxis.Expression = '<[BRAND] as [Brand Category] NEST [MARKET] as [Market]>'
visualContentObject.ColumnAxis.Expression = '<[Axis.Default.Names] as [Measure Names]>'
visualContentObject.ShowColumnGrandTotal = True
visualContentObject.ShowColumnSubtotals = True
visualContentObject.ShowRowGrandTotal = False
visualContentObject.Title = 'Monthly GS by Brand, Market'
visualContentObject.Data.WhereClauseExpression = '[NAME] = "CANADA"'
visualContentObject.CellWidth = 125
Document.Properties['cannedReportHideRows'] = 'Sum(Abs(SN([GS Month],0)))'
elif Document.Properties['cannedKPISelected'] == 'GS' and Document.Properties['cannedTimeSelected'] == 'Quarter' and percentageNeeded == 'Y':
visualContentObject = viz.As[VisualContent]()
visualContentObject.MeasureAxis.Expression = 'Sum([GS Quarter]) as [GS Qtr]'
visualContentObject.RowAxis.Expression = '<[BRAND] as [Brand] NEST [MARKET] as [Market]>'
visualContentObject.ColumnAxis.Expression = '<[Axis.Default.Names] as [Measure Names]>'
visualContentObject.ShowColumnGrandTotal = True
visualContentObject.ShowColumnSubtotals = True
visualContentObject.ShowRowGrandTotal = False
visualContentObject.Title = 'Quarterly GS by Brand, Market'
visualContentObject.Data.WhereClauseExpression = '[NAME] = "CANADA"'
visualContentObject.CellWidth = 125
Document.Properties['cannedReportHideRows'] = 'Sum(Abs(SN([GS Quarter],0)))'
So on and so forth.
This script (and others) run perfectly fine in the client. It does not run in the web. The web will say processing, then say ready (in the bottom left corner), all while doing nothing (no error, nothing). A few other scripts that I have in the same analysis run perfectly fine.
I know there are some limitations on IPython scripts on the web for security reasons, but I am only building a table. This cant be restricted can it? Web server logs are not capturing anything out of the ordinary.
We are on Spotfire 7.6
UPDATE: It seems to be due to this: if str(viz.Id) == 'a7f5b4ec-f545-4d5f-a967-adec4c9fec79':. This is because IDs are different between Web and Client unfortunately. Knowing my title changes as well, any ideas on what I could reference a visualization by that stays the same between client and web?
Because Spotfire changes IDs of a vis depending on whether it is on the web player vs the client, the script was not working as intended. I simply added the vis as a parameter instead of relying on the script to go and locate the correct vis. When the name of the vis changes, the parameter is updated correctly so it is still dynamic.
Could you just figure out what the index is on the current visual and refer to it that way?
Try something like:
Replace this line:
if str(viz.Id) == 'a7f5b4ec-f545-4d5f-a967-adec4c9fec79':
With:
if viz[0] (or whatever the index is)
Not sure if this is what you had in mind, but I believe this will give you a way to refer to the visualization without having to use an ID.
I have a Google Slides presentation with charts that are linked to a specific Google Sheets Spreadsheet.
As there are many charts in the presentation, I'm looking for a way to update all these linked charts automatically, or at least all of them at once.
What is the best way to do this?
You can add a custom function to a dropdown menu in the Slides UI with the following script. This gets the slides from the current presentation, loops through them, gets any charts in each slides and refreshes (updates) them.
function onOpen() {
var ui = SlidesApp.getUi();
ui.createMenu('Custom Menu')
.addItem('Batch Update Charts', 'batchUpdate')
.addToUi();
}
function batchUpdate(){
var gotSlides = SlidesApp.getActivePresentation().getSlides();
for (var i = 0; i < gotSlides.length; i++) {
var slide = gotSlides[i];
var sheetsCharts = slide.getSheetsCharts();
for (var k = 0; k < sheetsCharts.length; k++) {
var shChart = sheetsCharts[k];
shChart.refresh();
}
}
}
Note: The functionality to update/refresh linked Slides doesn't appear to exist at the time of this response.
You can find it in official documentation about API (for different lang).
https://developers.google.com/slides/how-tos/add-chart#refreshing_a_chart
You need to write a script for this and run it by schedule or manually.
I have found my own code that worked great.
from __future__ import print_function
import httplib2
import os
from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/slides.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/drive'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Google Slides API Python Quickstart'
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'slides.googleapis.com-python-quickstart.json')
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
"""Shows basic usage of the Slides API.
Creates a Slides API service object and prints the number of slides and
elements in a sample presentation:
"""
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('slides', 'v1', http=http)
# Here past your presentation id
presentationId = '1Owma9l9Z0Xjm1OPp-fcchdcxc1ImBPY2j9QH1LBDxtk'
presentation = service.presentations().get(
presentationId=presentationId).execute()
slides = presentation.get('slides')
print ('The presentation contains {} slides:'.format(len(slides)))
for slide in slides:
for element in slide['pageElements']:
presentation_chart_id = element['objectId']
# Execute the request.
try:
requests = [{'refreshSheetsChart': {'objectId': presentation_chart_id}}]
body = {'requests': requests}
#print(element)
requests = service.presentations().batchUpdate(
presentationId=presentationId, body=body).execute()
print('Refreshed a linked Sheets chart with ID: {0}'.format(presentation_chart_id))
except Exception:
pass
if __name__ == '__main__':
main()
Latest update: There is now an option in Slides's Tools drop-down menu to see all Linked Objects; the menu that appears has the option at the bottom to "Update all".
I know there are similar questions out there, but this one is a little different (I think).
I used the MATLAB Compiler to convert a .m to an Excel add-in. When I run the add-in on my machine, it works just fine. When I send it to a colleague, they get the "ActiveX component can't create object" error. They have added the add-in no problem.
Is there something going on here that's easily fixed?
MATLAB code:
function mess = createAndRouteOrderWithStyle()
c = startbbrg();
[num,text] = exportToM();
s = emsx('//blp/emapisvc_beta');
order.EMSX_ORDER_TYPE = text(1);
order.EMSX_SIDE = text(2);
order.EMSX_TICKER = text(3);
order.EMSX_AMOUNT = int32(num(1));
%order.EMSX_LIMIT_PRICE = num(2);
order.EMSX_BROKER = text(4);
order.EMSX_HAND_INSTRUCTION = text(5);
order.EMSX_TIF = text(6);
events = createOrderAndRoute(s,order);
mess = events.ERROR_MESSAGE;
close(s);
end
Excel VBA code:
Sub GO()
Cells(10,10).Formula = "=createAndRouteOrderWithStyle()"
End Sub