Skip to main content
Announcements
Live today at 11 AM ET. Get your questions about Qlik Connect answered, or just listen in. SIGN UP NOW
cancel
Showing results for 
Search instead for 
Did you mean: 
Mauritz_SA
Partner - Specialist
Partner - Specialist

Qlik Sense button to export object(s) as images

Hi everyone

We have started using NPrinting, but after creating a report I saw that one of the limitations is that I cannot use Alternate states which is an integral part of my app. I have a few graphs on different sheets and was wondering whether I can create a button to export about 6 objects as images (it can do exactly what the right-click export as Image does). Ideally I would like to be able to give it Object Ids as parameters in the sheet and then click on the button and it cycles through the object Ids I configured and it exports the. This might be a bit complicated so I can event hard code the Ids in the script for now or even create multiple buttons with only one Id in each.

I was wondering whether it is possible with a widget and if anyone has a code snippet I can re-use (I am very new to widgets)?

I built a Reload-App button using an example and was hoping for a similar solution.

Reload app widget. I was hoping for something similar to export the objects.Reload app widget. I was hoping for something similar to export the objects.

Any other suggestions are welcome.

Regards,

Mauritz

Labels (2)
1 Solution

Accepted Solutions
rankassovitz
Employee
Employee

Hello there @pwagner ,

There are a few ways to go about it while developing a widget or an extension. The  main difference between the 2 will be if you want to expose a configuration panel to the app developer (extension).

When the user clicks on your custom button:

  1. Get the list of object IDs to export (hard coded list, let end user pick from objects on the sheet or let the app developer to pre-define)
  2. Loop through it and run app.getObject(ID).exportImg(settings)

Here's a snippet that will present a downloadable link for each of the objects on the sheet:

extension.js

define( ["qlik", "text!./template.html"],
	function ( qlik, template ) {
		var extId;

		return {
			template: template,
			support: {
				snapshot: true,
				export: true,
				exportData: false
			},
			paint: function ($element, layout) {
				console.log(layout);
				extId = layout.qInfo.qId;
				return qlik.Promise.resolve();
			},
			controller: ['$scope', function ( $scope, layout ) {
				var settings = { format: 'png', height: 600, width: 900 }; // you could create custom properties and gather from layout
				var app = window.app = qlik.currApp();
				var sheetId = qlik.navigation.getCurrentSheetId().sheetId;
				var sheetObjects = [];
				
				$scope.finalObjects = [];
				
				// get objects of current sheet
				$scope.getSheetObjects = function() {
					// console.log(sheetId, extId);
					app.getObject(sheetId).then(function(qSheet){
						sheetObjects = qSheet.layout.qChildList.qItems;
						// console.log(sheetObjects);
						$scope.finalObjects = sheetObjects.filter(function(object) {
							return object.qInfo.qId != extId // filter out the extension object first
								&& object.qInfo.qType != 'filterpane'; // also filter out 'filterpane' -  you can't get an image from them
						});
						// you could now present the user with checkboxes for each of those objects and only then invoke the download
						// or you could automatically start downloading all objects with one click:
						$scope.downloadObjects($scope.finalObjects);
					})
				}
				
				// loop through array and get pngs
				$scope.downloadObjects = function(idArray) {
					console.log(idArray);
					idArray.map(function(object){
						console.log(object);
						app.visualization.get(object.qInfo.qId).then(function(vis){
							console.log(vis);
						  vis.exportImg(settings).then(function (result) {
							console.log('Image download link: ', result);
							object.downloadUrl = result;
							// maybe get binaries of all files and collect them to 1 zip file using a library like JSZip
						  });
						});
					});
				}
			}]
		};

	} );

 

template.html

<div qv-extension style="height: 100%; position: relative; overflow: auto;" class="ng-scope">
	<button ng-click="getSheetObjects()">
		Download Sheet Objects
	</button>
	
	<ul ng-if="finalObjects.length">
		<li ng-repeat="o in finalObjects">
			<a href="{{ o.downloadUrl }}" target="_blank">{{ o.qData.title }}</a>
		</li>
	</ul>
</div>

View solution in original post

4 Replies
pwagner
Partner - Creator III
Partner - Creator III

Hi @Mauritz_SA 
Have you found a solution for your topic?
Regards, Patrick

rankassovitz
Employee
Employee

Hello there @pwagner ,

There are a few ways to go about it while developing a widget or an extension. The  main difference between the 2 will be if you want to expose a configuration panel to the app developer (extension).

When the user clicks on your custom button:

  1. Get the list of object IDs to export (hard coded list, let end user pick from objects on the sheet or let the app developer to pre-define)
  2. Loop through it and run app.getObject(ID).exportImg(settings)

Here's a snippet that will present a downloadable link for each of the objects on the sheet:

extension.js

define( ["qlik", "text!./template.html"],
	function ( qlik, template ) {
		var extId;

		return {
			template: template,
			support: {
				snapshot: true,
				export: true,
				exportData: false
			},
			paint: function ($element, layout) {
				console.log(layout);
				extId = layout.qInfo.qId;
				return qlik.Promise.resolve();
			},
			controller: ['$scope', function ( $scope, layout ) {
				var settings = { format: 'png', height: 600, width: 900 }; // you could create custom properties and gather from layout
				var app = window.app = qlik.currApp();
				var sheetId = qlik.navigation.getCurrentSheetId().sheetId;
				var sheetObjects = [];
				
				$scope.finalObjects = [];
				
				// get objects of current sheet
				$scope.getSheetObjects = function() {
					// console.log(sheetId, extId);
					app.getObject(sheetId).then(function(qSheet){
						sheetObjects = qSheet.layout.qChildList.qItems;
						// console.log(sheetObjects);
						$scope.finalObjects = sheetObjects.filter(function(object) {
							return object.qInfo.qId != extId // filter out the extension object first
								&& object.qInfo.qType != 'filterpane'; // also filter out 'filterpane' -  you can't get an image from them
						});
						// you could now present the user with checkboxes for each of those objects and only then invoke the download
						// or you could automatically start downloading all objects with one click:
						$scope.downloadObjects($scope.finalObjects);
					})
				}
				
				// loop through array and get pngs
				$scope.downloadObjects = function(idArray) {
					console.log(idArray);
					idArray.map(function(object){
						console.log(object);
						app.visualization.get(object.qInfo.qId).then(function(vis){
							console.log(vis);
						  vis.exportImg(settings).then(function (result) {
							console.log('Image download link: ', result);
							object.downloadUrl = result;
							// maybe get binaries of all files and collect them to 1 zip file using a library like JSZip
						  });
						});
					});
				}
			}]
		};

	} );

 

template.html

<div qv-extension style="height: 100%; position: relative; overflow: auto;" class="ng-scope">
	<button ng-click="getSheetObjects()">
		Download Sheet Objects
	</button>
	
	<ul ng-if="finalObjects.length">
		<li ng-repeat="o in finalObjects">
			<a href="{{ o.downloadUrl }}" target="_blank">{{ o.qData.title }}</a>
		</li>
	</ul>
</div>
pwagner
Partner - Creator III
Partner - Creator III

Hello @rankassovitz 

Great - thank you. It works.

I changed it from  exportImg to exportPdf.

 

Best regards, Patrick

pwagner
Partner - Creator III
Partner - Creator III

Hi @rankassovitz 

During my further tests I found out, that in the PDF I find only a certain number of lines. Unfortunately I does not correspond with the shown lines in the Qlik Sense app.

Do you have an idea what I have to change in the code of the extension?

 

pwagner_0-1675168037136.png

 

Thank you.

 

Best regards,

Patrick