如何使用Python将图像添加到PDF并从esri地理数据库表创建报告

时间:2017-12-14 18:13:01

标签: python matplotlib pdf-generation esri arcpy

我有一个旧脚本,它使用SSReport创建并生成添加一些基本数据的PDF。我想更新它以包含图像文件并循环浏览一些esri地理数据库表。我使用2.7在SSReport库上看不到太多文档。有更新/更好的方式吗?

如果可能的话,我不想安装第三方套餐。

import SSReport as REPORT
pdfOutput = REPORT.openPDF(fileName)

#Set up Table
NumColumns = 4
report = REPORT.startNewReport(NumColumns,
                               title = 'Report ',
                               landscape = False,
                               numRows = "", # probably empty
                               titleFont = REPORT.ssTitleFont)

grid = report.grid
grid.writeCell((grid.rowCount, 1),"hello world",justify = "left",)
grid.finalizeTable() # Will fill empty rows with spaces.
report.write(pdfOutput) # write to PDF

1 个答案:

答案 0 :(得分:0)

总体而言,我想创建一个PDF报告,其中包含一个地图,以及存储在Esri地理数据库中的图像和一些表格数据。由于缺乏上述方法和时间紧缩的信息,我最终依靠arcpy.Mapping来更新包括图像的地图图层元素并导出布局。

我使用MatplotLib生成其他图表和表格,因为有许多示例和线程可以提供帮助。同时安装了ArcGIS Desktop和Server,以避免为客户端安装第三方库的先决条件。

以下是样本:

import matplotlib.pyplot as plt
import xlrd
import xlwt
import datetime
import os
import glob
import arcpy
import SSReport as REPORT
import numpy as NUM
from matplotlib.backends.backend_pdf import PdfPages as PDF
import matplotlib.pyplot as PLT

# get path for mxd template from location of script
filePath = os.path.dirname(os.path.abspath(__file__))
templatePath = os.path.join(filePath,"templates")

def TabletoPDF2(outdir, outputPDF):

    tables = [os.path.join(outdir,'scratch.gdb', 'table1'),
              os.path.join(outdir, 'scratch.gdb', 'table2')]

    pp = PDF(outputPDF)

    for table in tables:
        # convert to format for creating charts.
        ntab = arcpy.da.TableToNumPyArray(table, "*")
        columns = [fld for fld in ntab.dtype.names if fld not in ["OBJECTID"]]
        cell_text = []
        for row in ntab.tolist():
            cell_text.append(row[1:])

        fig = PLT.figure(figsize=(8.2, 10.6))

        # Create PIECHART (percent lengeth)
        ax1 = PLT.subplot(211)

        data = ntab["percent_len"].tolist()
        vals = [x for x in data if x > 0.]
        labels = ntab[columns[0]].tolist()
        labels = [n for n, v in zip(labels, data) if v > 0]
        ax1.pie(vals, autopct='%1.1f%%', shadow=True, startangle=90)
        ax1.axis('equal')
        ax1.legend(labels, loc='center right', fontsize=8, bbox_to_anchor=(1, 1))

        # Create TABLE of values
        ax2 = PLT.subplot(212)
        the_table = PLT.table(cellText=cell_text, colLabels=columns, loc='center')
        the_table.auto_set_font_size(True)
        PLT.axis('off')

        PLT.tight_layout()

        #### Set Title ####
        title = os.path.basename(table)
        PLT.suptitle(title, fontsize=11, fontweight='bold')

        pp.savefig(fig)
    pp.close()

    return outputPDF


def CreatePDFReport(sPath, outprofilegraph, sfroute_feat):

    template_mxd_filename = os.path.join(templatePath,'Reportemplate.mxd')

    layoutpdf_filename = os.path.join(sPath,'Layout.pdf')
    tablepdf_filename = os.path.join(sPath,'TableReport.pdf')
    finalpdf_filename  = os.path.join(sPath,'Final Report.pdf')

    #Create layout report (page1)
    arcpy.AddMessage("Creating Layout...")
    arcpy.AddMessage(template_mxd_filename)
    mxd = arcpy.mapping.MapDocument(template_mxd_filename)
    change_picture_element(mxd, outprofilegraph)
    change_layer_source(mxd, sfroute_feat)
    arcpy.mapping.ExportToPDF(mxd,layoutpdf_filename)

    # Create Table Report(page2)
    TablePDF = CreateTableReport(tablepdf_filename)
    TablePDF = TabletoPDF2(sPath, tablepdf_filename)

    #Create Final report (merge)
    msg = ("Creating Output Report {}".format(finalpdf_filename))
    arcpy.AddMessage(msg)
    if os.path.exists(finalpdf_filename):
      os.remove(finalpdf_filename)
    pdfFinal = arcpy.mapping.PDFDocumentCreate(finalpdf_filename)
    pdfFinal.appendPages(layoutpdf_filename)
    pdfFinal.appendPages(TablePDF)
    pdfFinal.saveAndClose()

    os.remove(tablepdf_filename)
    os.remove(layoutpdf_filename)

    return finalpdf_filename


def change_layer_source(mxd, route_feat):
    """ Update layer datasource and zoom to extent """

    arcpy.AddMessage(route_feat)
    replace_workspace_path, datasetname = os.path.split(route_feat)


    df = arcpy.mapping.ListDataFrames(mxd)[0]
    for lyr in arcpy.mapping.ListLayers(mxd, data_frame=df):
        if lyr.name == 'RouteLayer':
            lyr.replaceDataSource (replace_workspace_path, "None")
            ext = lyr.getExtent()
            df.extent = ext
    # mxd.save()

def change_picture_element(mxd, outprofilegraph):
    for elm in arcpy.mapping.ListLayoutElements(mxd, "PICTURE_ELEMENT"):
        if elm.name == "elevprofile":
            elm.sourceImage = outprofilegraph
    # mxd.save()


if __name__ == '__main__':

    folderPath = arcpy.GetParameterAsText(0)
    inTable = arcpy.GetParameterAsText(1)
    sfroute_feat = arcpy.GetParameterAsText(2)

    finalReport = CreatePDFReport(folderPath, outprofilegraph, sfroute_feat)

    # Set outputs
    arcpy.SetParameterAsText(4, finalReport)