PDF View Plugin

PDF View Plugin for JIRA is a highly configurable PDF exporter, that is easily scriptable through its API. Used together with ScriptRunner, it can generate, distribute or locally save your periodic JIRA issue reports or other PDF documents. For more technical information about the PDF API, the interface exposed by the PDF View Plugin, please see it’s documentation here

These examples below are fairly simple, but the possible use cases are limitless. ScriptRunner is a perfect tool to fully take advantage of the flexibility of PDF View Plugin and effortlessly create the more complex documents that support your custom business need or internal process.

Emailing a PDF document from an issue during a transition:

This is a simple workflow postfunction example to generate a custom PDF document from the transitioned issue and send that attached to a custom email

import javax.activation.DataHandler
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMultipart
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.util.ByteArrayDataSource
import com.atlassian.mail.Email
import com.atlassian.mail.queue.SingleMailQueueItem

// PDF configuration
def templateName = "issue-fo.vm"
def title = "My sample PDF document"

// email configuration
def to = "adam@acme.com, bob@acme.com, cecil@acme.com" // can contain multiple addresses in a comma-separated list
def subject = "Post-function executed on ${issue.key}"
def body = "See the PDF document generated from \"${issue.summary}\" in the attachment!"

// render the PDF
def user = ComponentAccessor.jiraAuthenticationContext?.user
def pdfApiClass = this.class.forName('com.midori.jira.plugin.pdfview.api.PdfApi', true, ComponentAccessor.pluginAccessor.classLoader)
def pdfApi = ComponentAccessor.getOSGiComponentInstanceOfType(pdfApiClass)
ComponentAccessor.jiraAuthenticationContext.setLoggedInUser(user)
def pdfResult = pdfApi.getPdf(templateName, title.toString(), [ issue ], [:])

// send email
to.tokenize(",").each() {
    def dataSource = new ByteArrayDataSource(new ByteArrayInputStream(pdfResult.bytes), "application/pdf")
    def attachmentPart = new MimeBodyPart(dataHandler : new DataHandler(dataSource), fileName : pdfResult.fileName)
    def multipart = new MimeMultipart("mixed")
    multipart.addBodyPart(attachmentPart)

    def email = new Email(it.trim())
    email.subject = subject
    email.body = body
    email.multipart = multipart
    ComponentAccessor.mailQueue.addItem(new SingleMailQueueItem(email))
}

Periodically run JQL and exporting results to PDF:

This example can be installed as a Groovy service to run a JQL query, generate a PDF document from the results and save it to the filesystem.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import org.springframework.util.FileCopyUtils

// PDF configuration
def userName = "admin" // this user runs the search and generates the PDF
def jql = "updated > -24h"
def templateName = "issue-fo.vm"
def title = "Issues updated in the last 24 hours"

// run the search
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def query = jqlQueryParser.parseQuery(jql)
def searchProvider = ComponentAccessor.getComponent(SearchProvider)
def user = ComponentAccessor.userUtil.getUser(userName)
def results = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())

// render the PDF
def issues = results.issues
if(issues) {
    def pdfApiClass = this.class.forName('com.midori.jira.plugin.pdfview.api.PdfApi', true, ComponentAccessor.pluginAccessor.classLoader)
    def pdfApi = ComponentAccessor.getOSGiComponentInstanceOfType(pdfApiClass)
    ComponentAccessor.jiraAuthenticationContext.setLoggedInUser(user)
    def pdfResult = pdfApi.getPdf(templateName, title.toString(), issues, [:])

// do whatever you want to do with the PDF
// (in this example, we just write it to a file with a timestamped filename like "example-20170526-1304.pdf")
    FileCopyUtils.copy(pdfResult.bytes, new File("c:\\tmp\\example-${new Date().format('yyyyMMdd-HHmm')}.pdf"))
}

Better Excel Plugin

ScriptRunner can be used with Better Excel Plugin for JIRA to create, email or locally save your JIRA issue exports or reports in native Excel format. Better Excel Plugin is deeply customizable and allows you to use the native Excel reporting features (pivot reports, pivot charts, functions, formulas) on your JIRA data. For more technical information about Better Excel Plugin and it’s API, visit its documentation here.

Below are two simple examples of emailing and saving a JIRA Excel export. You can, however, generate even the most complex Business Intelligence reports and more by scripting, thanks to the flexibility of ScriptRunner and Better Excel Plugin.

Emailing an Excel file after a transition

This is a simple workflow postfunction example to export a transitioned issue to an Excel file and send that attached to a custom email.

import javax.activation.DataHandler
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMultipart
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.util.ByteArrayDataSource
import com.atlassian.mail.Email
import com.atlassian.mail.queue.SingleMailQueueItem
// XLSX configuration
def templateName = "issue-navigator.xlsx"
def title = "My sample Excel document"
// email configuration
def to = "adam@acme.com, bob@acme.com, cecil@acme.com" // can contain multiple addresses in a comma-separated list
def subject = "Post-function executed on ${issue.key}"
def body = "See the Excel document generated from \"${issue.summary}\" in the attachment!"
// render the XLSX
def user = ComponentAccessor.jiraAuthenticationContext?.user
def xlsApiClass = this.class.forName('com.midori.jira.plugin.betterexcel.api.XlsApi', true, ComponentAccessor.pluginAccessor.classLoader)
def xlsApi = ComponentAccessor.getOSGiComponentInstanceOfType(xlsApiClass)
ComponentAccessor.jiraAuthenticationContext.setLoggedInUser(user)
def xlsResult = xlsApi.getXls(templateName, title.toString(), [ issue ], [:])
// send email
to.tokenize(",").each() {
    def dataSource = new ByteArrayDataSource(new ByteArrayInputStream(xlsResult.bytes), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    def attachmentPart = new MimeBodyPart(dataHandler : new DataHandler(dataSource), fileName : xlsResult.fileName)
    def multipart = new MimeMultipart("mixed")
    multipart.addBodyPart(attachmentPart)
    def email = new Email(it.trim())
    email.subject = subject
    email.body = body
    email.multipart = multipart
    ComponentAccessor.mailQueue.addItem(new SingleMailQueueItem(email))
}

Running a JQL search and exporting the result to an Excel file

This example can be installed as a Groovy service to run a JQL query, generate an Excel spreadsheet from the results and save it to the filesystem.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import org.springframework.util.FileCopyUtils
// XLSX configuration
def userName = "admin" // this user runs the search and generates the XLSX
def jql = "updated > -24h"
def templateName = "issue-navigator.xlsx"
def title = "Issues updated in the last 24 hours"
// run the search
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def query = jqlQueryParser.parseQuery(jql)
def searchProvider = ComponentAccessor.getComponent(SearchProvider)
def user = ComponentAccessor.userUtil.getUser(userName)
def results = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())
// render the XLSX
def issues = results.issues
if(issues) {
    def xlsApiClass = this.class.forName('com.midori.jira.plugin.betterexcel.api.XlsApi', true, ComponentAccessor.pluginAccessor.classLoader)
    def xlsApi = ComponentAccessor.getOSGiComponentInstanceOfType(xlsApiClass)
    ComponentAccessor.jiraAuthenticationContext.setLoggedInUser(user)
    def xlsResult = xlsApi.getXls(templateName, title.toString(), issues, [:])
// do whatever you want to do with the XLSX
// (in this example, we just write it to a file with a timestamped filename like "example-20170526-1304.xlsx")
    FileCopyUtils.copy(xlsResult.bytes, new File("c:\\tmp\\example-${new Date().format('yyyyMMdd-HHmm')}.xlsx"))
}

For how-to questions please ask on Atlassian Answers where there is a very active community. Adaptavist staff are also likely to respond there.

Ask a question about ScriptRunner for JIRA, for for Bitbucket Server, or for Confluence.