Пример #1
0
def importxml(db, xmlinput):
    """
        Converts the XML to a CSV compatible with the import_from_csv_file of web2py
        @ToDo: rewrite this to go via S3Resource for proper Auth checking, Audit.

        @todo: deprecate
    """

    from s3compat import StringIO
    import xml.dom.minidom

    try:
        doc = xml.dom.minidom.parseString(xmlinput)
    except:
        raise Exception("XML parse error")

    parent = doc.childNodes[0].tagName
    csvout = csvheader(parent, doc.childNodes[0].childNodes)
    for subnode in doc.childNodes:
        csvout = csvout + csvdata(subnode.childNodes)
    fh = StringIO()
    fh.write(csvout)
    fh.seek(0, 0)
    db[parent].import_from_csv_file(fh)
Пример #2
0
    def import_xls(uploadFile):
        """
            Import Assessment Spreadsheet
        """

        from s3compat import StringIO

        if series_id is None:
            response.error = T("Series details missing")
            return
        openFile = StringIO()
        try:
            import xlrd
            from xlwt.Utils import cell_to_rowcol2
        except ImportError:
            current.log.error("ERROR: xlrd & xlwt modules are needed for importing spreadsheets")
            return None
        workbook = xlrd.open_workbook(file_contents=uploadFile)
        try:
            sheetR = workbook.sheet_by_name("Assessment")
            sheetM = workbook.sheet_by_name("Metadata")
        except:
            session.error = T("You need to use the spreadsheet which you can download from this page")
            redirect(URL(c="survey", f="new_assessment", args=[],
                         vars={"viewing": "survey_series.%s" % series_id}))
        header = ""
        body = ""
        for row in xrange(1, sheetM.nrows):
            header += ',"%s"' % sheetM.cell_value(row, 0)
            code = sheetM.cell_value(row, 0)
            qstn = s3.survey_getQuestionFromCode(code, series_id)
            type = qstn["type"]
            count = sheetM.cell_value(row, 1)
            if count != "":
                count = int(count)
                optionList = sheetM.cell_value(row, 2).split("|#|")
            else:
                count = 1
                optionList = None
            if type == "Location" and optionList != None:
                answerList = {}
            elif type == "MultiOption":
                answerList = []
            else:
                answerList = ""
            for col in range(count):
                cell = sheetM.cell_value(row, 3 + col)
                (rowR, colR) = cell_to_rowcol2(cell)
                try:
                    cellValue = sheetR.cell_value(rowR, colR)
                except IndexError:
                    cellValue = ""
                # BUG: The option list needs to work in different ways
                # depending on the question type. The question type should
                # be added to the spreadsheet to save extra db calls:
                # * Location save all the data as a hierarchy
                # * MultiOption save all selections
                # * Option save the last selection
                if cellValue != "":
                    if optionList != None:
                        if type == "Location":
                            answerList[optionList[col]]=cellValue
                        elif type == "MultiOption":
                            answerList.append(optionList[col])
                        else:
                            answerList = optionList[col]
                    else:
                        if type == "Date":
                            try:
                                (dtYear, dtMonth, dtDay, dtHour, dtMinute, dtSecond) = \
                                         xlrd.xldate_as_tuple(cellValue,
                                                              workbook.datemode)
                                dtValue = datetime.date(dtYear, dtMonth, dtDay)
                                cellValue = dtValue.isoformat()
                            except:
                                pass
                        elif type == "Time":
                            try:
                                time = cellValue
                                hour = int(time * 24)
                                minute = int((time * 24 - hour) * 60)
                                cellValue = "%s:%s" % (hour, minute)
                            except:
                                pass
                        answerList += "%s" % cellValue
            body += ',"%s"' % answerList
        openFile.write(header)
        openFile.write("\n")
        openFile.write(body)
        openFile.seek(0)
        return openFile
Пример #3
0
    def encode(self, resource, **attr):
        """
            API Method to encode a resource as cards

            @param resource: the S3Resource, or
                             - the data items as list [{fieldname: representation, ...}, ...], or
                             - a callable that produces such a list of items
            @param attr: additional encoding parameters (see below)

            @keyword layout: the layout (a S3PDFCardLayout subclass, overrides
                             the resource's pdf_card_layout setting
            @keyword orderby: orderby-expression for data extraction, overrides
                              the resource's orderby setting
            @keyword labels: the labels for the fields,
                             - a dict {colname: label}, or
                             - a callable that produces it,
                             - defaults to the labels of the extracted fields
            @keyword pagesize: the PDF page size,
                               - a string "A4" or "Letter", or
                               - a tuple (width, height), in points
                               - defaults to the layout's card size
            @keyword margins: the page margins,
                              - a tuple (N, E, S, W), in points, or
                              - a single number, in points
                              - will be computed if omitted
            @keyword spacing: the spacing between cards,
                              - a tuple (H, V), in points, or
                              - a single number, in points
                              - defaults to 18 points in both directions
            @keyword title: the document title,
                            - defaults to title_list crud string of the resource

            @return: a handle to the output
        """

        if not REPORTLAB:
            # FIXME is this the correct handling of a dependency failure?
            raise HTTP(503, "Python ReportLab library not installed")

        # Do we operate on a S3Resource?
        is_resource = isinstance(resource, S3Resource)

        # The card layout
        layout = attr.get("layout")
        if layout is None and is_resource:
            layout = resource.get_config("pdf_card_layout")
        if layout is None:
            layout = S3PDFCardLayout

        # Card (and hence page) orientation
        orientation = layout.orientation
        if orientation == "Landscape":
            orientation = landscape
        else:
            orientation = portrait

        # Card and page size
        cardsize = orientation(layout.cardsize)
        pagesize = attr.get("pagesize")
        if pagesize == "A4":
            pagesize = A4
        elif pagesize == "Letter":
            pagesize = LETTER
        elif not isinstance(pagesize, (tuple, list)):
            pagesize = cardsize
        pagesize = orientation(pagesize)

        # Extract the data
        if is_resource:
            # Extract the data items from the resource
            fields = layout.fields(resource)
            data = self.extract(resource, fields, orderby=attr.get("orderby"))
            items = data.rows
        elif callable(resource):
            # External getter => call with resource, returns the data items
            data = None
            items = resource()
        else:
            # The data items have been passed-in in place of the resource
            data = None
            items = resource

        # Get the labels
        labels = attr.get("labels")
        if callable(labels):
            labels = labels(resource)
        elif not isinstance(labels, dict):
            if data and hasattr(data, "rfields"):
                # Collect the labels from rfields
                rfields = data.rfields
                labels = {rfield.colname: rfield.label for rfield in rfields}
            else:
                labels = {}

        # Document title
        title = attr.get("title")
        if not title and is_resource:
            crud_strings = current.response.s3.crud_strings[resource.tablename]
            if crud_strings:
                title = crud_strings["title_list"]

        # Instantiate the doc template
        doc = S3PDFCardTemplate(
            pagesize,
            cardsize,
            margins=attr.get("margins"),
            spacing=attr.get("spacing"),
            title=title,
        )

        # Produce the flowables
        flowables = self.get_flowables(
            layout,
            resource,
            items,
            labels=labels,
            cards_per_page=doc.cards_per_page,
        )

        # Build the doc
        output_stream = StringIO()
        doc.build(
            flowables,
            output_stream,
            #canvasmaker=canvas.Canvas,   # is default
        )

        output_stream.seek(0)
        return output_stream
Пример #4
0
    def xls(self, r, **attr):
        """
            Export the performance indicators as XLS data sheet

            @param r: the S3Request instance
            @param attr: controller attributes
        """

        T = current.T
        s3db = current.s3db

        try:
            import xlwt
        except ImportError:
            raise HTTP(503, body="XLWT not installed")

        title = s3_str(T("Performance Indicators"))
        write = self.write

        # Create workbook and sheet
        book = xlwt.Workbook(encoding="utf-8")
        sheet = book.add_sheet(title)

        # Get the statistics
        resource = self.resource
        table = resource.table
        indicators = self.indicators(resource)

        # Title and Report Dates (from filter)
        write(sheet, 0, 0, title, style="header")
        dates = []
        get_vars = r.get_vars
        field = table.date
        for fvar in ("~.date__ge", "~.date__le"):
            dtstr = get_vars.get(fvar)
            if dtstr:
                try:
                    dt = s3_decode_iso_datetime(dtstr).date()
                except (ValueError, AttributeError):
                    dt = None
                else:
                    dates.append(field.represent(dt))
            else:
                dates.append("...")
        if dates:
            write(sheet, 1, 0, " -- ".join(dates))

        # Basic performance indicators
        rowindex = 3
        # Total number of consultations
        write(sheet, rowindex, 0, T("Total Number of Consultations"))
        write(sheet, rowindex, 1, indicators.get("total_responses", ""))

        rowindex += 1
        write(sheet, rowindex, 0, T("Total Number of Clients"))
        write(sheet, rowindex, 1, indicators.get("total_clients", ""))

        rowindex += 1
        write(sheet, rowindex, 0, T("Average Duration of Consultations (minutes)"))
        avg_hours_per_response = indicators.get("avg_hours_per_response")
        if avg_hours_per_response:
            avg_minutes_per_response = int(round(avg_hours_per_response * 60))
        else:
            avg_minutes_per_response = ""
        write(sheet, rowindex, 1, avg_minutes_per_response)

        rowindex += 1
        write(sheet, rowindex, 0, T("Average Number of Consultations per Client"))
        write(sheet, rowindex, 1, indicators.get("avg_responses_per_client", ""))

        # Distribution
        rowindex = 8
        write(sheet, rowindex, 0, T("Distribution of Clients"))

        write(sheet, rowindex, 1, T("Single"))
        write(sheet, rowindex, 2, indicators.get("singles", ""))

        rowindex += 1
        write(sheet, rowindex, 1, T("Family"))
        write(sheet, rowindex, 2, indicators.get("families", ""))

        rowindex += 1
        write(sheet, rowindex, 1, T("Group Counseling"))

        rowindex += 1
        write(sheet, rowindex, 1, T("Individual Counseling"))
        write(sheet, rowindex, 2, indicators.get("total_responses", ""))

        # Top-5's
        rowindex = 13
        write(sheet, rowindex, 0, T("Top 5 Countries of Origin"))
        top_5_nationalities = indicators.get("top_5_nationalities")
        if top_5_nationalities:
            dtable = s3db.pr_person_details
            field = dtable.nationality
            for rank, nationality in enumerate(top_5_nationalities):
                write(sheet, rowindex, 1, "%s - %s" % (rank + 1, field.represent(nationality)))
                rowindex += 1

        rowindex += 1
        write(sheet, rowindex, 0, T("Top 5 Counseling Reasons"))
        top_5_needs = indicators.get("top_5_needs")
        if top_5_needs:
            ttable = s3db.dvr_response_theme
            field = ttable.need_id
            for rank, need in enumerate(top_5_needs):
                write(sheet, rowindex, 1, "%s - %s" % (rank + 1, field.represent(need)))
                rowindex += 1

        # Output
        output = StringIO()
        book.save(output)
        output.seek(0)

        # Response headers
        from gluon.contenttype import contenttype
        disposition = "attachment; filename=\"%s\"" % "indicators.xls"
        response = current.response
        response.headers["Content-Type"] = contenttype(".xls")
        response.headers["Content-disposition"] = disposition

        from gluon.streamer import DEFAULT_CHUNK_SIZE
        return response.stream(output,
                               chunk_size=DEFAULT_CHUNK_SIZE,
                               request=r,
                               )
Пример #5
0
def item_export_pdf():
    """
        Export a list of Items in Adobe PDF format
        Uses Geraldo Grouping Report
        @ToDo: Use S3PDF Method
    """
    try:
        from reportlab.lib.units import cm
        from reportlab.lib.pagesizes import A4
        from reportlab.lib.enums import TA_CENTER, TA_RIGHT
    except ImportError:
        session.error = "Python needs the ReportLab module installed for PDF export"
        redirect(URL(c="item"))
    try:
        from geraldo import Report, ReportBand, ReportGroup, Label, ObjectValue, SystemField, landscape, BAND_WIDTH
        from geraldo.generators import PDFGenerator
    except ImportError:
        session.error = "Python needs the Geraldo module installed for PDF export"
        redirect(URL(c="item"))

    table = db.budget_item
    objects_list = db(table.id > 0).select(orderby=table.category_type)
    if not objects_list:
        session.warning = T("No data in this table - cannot create PDF!")
        redirect(URL(f="item"))

    from s3compat import StringIO
    output = StringIO()

    class MyReport(Report):
        def __init__(self, queryset=None, T=None):
            " Initialise parent class & make any necessary modifications "
            Report.__init__(self, queryset)
            self.T = T

        def _T(self, rawstring):
            return self.T(rawstring)

        # can't use T() here!
        #title = _T("Items")
        title = "Items"
        page_size = landscape(A4)

        class band_page_header(ReportBand):
            height = 1.3 * cm
            elements = [
                SystemField(expression="%(report_title)s",
                            top=0.1 * cm,
                            left=0,
                            width=BAND_WIDTH,
                            style={
                                "fontName": "Helvetica-Bold",
                                "fontSize": 14,
                                "alignment": TA_CENTER
                            }),
                Label(text="Code", top=0.8 * cm, left=0.2 * cm),
                Label(text="Description", top=0.8 * cm, left=3 * cm),
                Label(text="Unit Cost", top=0.8 * cm, left=13 * cm),
                Label(text="per Month", top=0.8 * cm, left=15 * cm),
                Label(text="per Minute", top=0.8 * cm, left=17 * cm),
                Label(text="per Megabyte", top=0.8 * cm, left=19 * cm),
                Label(text="Comments", top=0.8 * cm, left=21 * cm),
            ]
            borders = {"bottom": True}

        class band_page_footer(ReportBand):
            height = 0.5 * cm
            elements = [
                Label(text="%s" % request.utcnow.date(), top=0.1 * cm, left=0),
                SystemField(
                    expression="Page # %(page_number)d of %(page_count)d",
                    top=0.1 * cm,
                    width=BAND_WIDTH,
                    style={"alignment": TA_RIGHT}),
            ]
            borders = {"top": True}

        class band_detail(ReportBand):
            height = 0.5 * cm
            auto_expand_height = True
            elements = (
                ObjectValue(attribute_name="code",
                            left=0.2 * cm,
                            width=2.8 * cm),
                ObjectValue(attribute_name="description",
                            left=3 * cm,
                            width=10 * cm),
                ObjectValue(attribute_name="unit_cost",
                            left=13 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="monthly_cost",
                            left=15 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="minute_cost",
                            left=17 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="megabyte_cost",
                            left=19 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="comments",
                            left=21 * cm,
                            width=6 * cm),
            )

        groups = [
            ReportGroup(
                attribute_name="category_type",
                band_header=ReportBand(
                    height=0.7 * cm,
                    elements=[
                        ObjectValue(
                            attribute_name="category_type",
                            left=0,
                            top=0.1 * cm,
                            get_value=lambda instance: instance.category_type
                            and budget_category_type_opts[instance.
                                                          category_type],
                            style={
                                "fontName": "Helvetica-Bold",
                                "fontSize": 12
                            })
                    ],
                    borders={"bottom": True},
                ),
            ),
        ]

    #report = MyReport(queryset=objects_list)
    report = MyReport(queryset=objects_list, T=T)
    report.generate_by(PDFGenerator, filename=output)

    output.seek(0)
    import gluon.contenttype
    response.headers["Content-Type"] = gluon.contenttype.contenttype(".pdf")
    filename = "%s_items.pdf" % (request.env.server_name)
    response.headers[
        "Content-disposition"] = "attachment; filename=\"%s\"" % filename
    return output.read()
Пример #6
0
def kit_export_pdf():
    """
        Export a list of Kits in Adobe PDF format
        Uses Geraldo SubReport
        @ToDo: Use S3PDF Method
    """
    try:
        from reportlab.lib.units import cm
        from reportlab.lib.pagesizes import A4
        from reportlab.lib.enums import TA_CENTER, TA_RIGHT
    except ImportError:
        session.error = "Python needs the ReportLab module installed for PDF export"
        redirect(URL(c="kit"))
    try:
        from geraldo import Report, ReportBand, SubReport, Label, ObjectValue, SystemField, landscape, BAND_WIDTH
        from geraldo.generators import PDFGenerator
    except ImportError:
        session.error = "Python needs the Geraldo module installed for PDF export"
        redirect(URL(c="kit"))

    table = db.budget_kit
    objects_list = db(table.id > 0).select()
    if not objects_list:
        session.warning = T("No data in this table - cannot create PDF!")
        redirect(URL(r=request))

    from s3compat import StringIO
    output = StringIO()

    #class MySubReport(SubReport):
    #    def __init__(self, db=None, **kwargs):
    #        " Initialise parent class & make any necessary modifications "
    #        self.db = db
    #        SubReport.__init__(self, **kwargs)

    class MyReport(Report):
        def __init__(self, queryset=None, db=None):
            " Initialise parent class & make any necessary modifications "
            Report.__init__(self, queryset)
            self.db = db

        # can't use T() here!
        title = "Kits"
        page_size = landscape(A4)

        class band_page_header(ReportBand):
            height = 1.3 * cm
            elements = [
                SystemField(expression="%(report_title)s",
                            top=0.1 * cm,
                            left=0,
                            width=BAND_WIDTH,
                            style={
                                "fontName": "Helvetica-Bold",
                                "fontSize": 14,
                                "alignment": TA_CENTER
                            }),
                Label(text="Code", top=0.8 * cm, left=0.2 * cm),
                Label(text="Description", top=0.8 * cm, left=2 * cm),
                Label(text="Cost", top=0.8 * cm, left=10 * cm),
                Label(text="Monthly", top=0.8 * cm, left=12 * cm),
                Label(text="per Minute", top=0.8 * cm, left=14 * cm),
                Label(text="per Megabyte", top=0.8 * cm, left=16 * cm),
                Label(text="Comments", top=0.8 * cm, left=18 * cm),
            ]
            borders = {"bottom": True}

        class band_page_footer(ReportBand):
            height = 0.5 * cm
            elements = [
                Label(text="%s" % request.utcnow.date(), top=0.1 * cm, left=0),
                SystemField(
                    expression="Page # %(page_number)d of %(page_count)d",
                    top=0.1 * cm,
                    width=BAND_WIDTH,
                    style={"alignment": TA_RIGHT}),
            ]
            borders = {"top": True}

        class band_detail(ReportBand):
            height = 0.5 * cm
            auto_expand_height = True
            elements = (
                ObjectValue(attribute_name="code",
                            left=0.2 * cm,
                            width=1.8 * cm),
                ObjectValue(attribute_name="description",
                            left=2 * cm,
                            width=8 * cm),
                ObjectValue(attribute_name="total_unit_cost",
                            left=10 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="total_monthly_cost",
                            left=12 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="total_minute_cost",
                            left=14 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="total_megabyte_cost",
                            left=16 * cm,
                            width=2 * cm),
                ObjectValue(attribute_name="comments",
                            left=18 * cm,
                            width=6 * cm),
            )

        subreports = [
            SubReport(
                #queryset_string = "db((db.budget_kit_item.kit_id == %(object)s.id) & (db.budget_item.id == db.budget_kit_item.item_id)).select(db.budget_item.code, db.budget_item.description, db.budget_item.unit_cost)",
                #queryset_string = "db(db.budget_kit_item.kit_id == %(object)s.id).select()",
                band_header=ReportBand(
                    height=0.5 * cm,
                    elements=[
                        Label(text="Item ID",
                              top=0,
                              left=0.2 * cm,
                              style={"fontName": "Helvetica-Bold"}),
                        Label(text="Quantity",
                              top=0,
                              left=2 * cm,
                              style={"fontName": "Helvetica-Bold"}),
                        #Label(text="Unit Cost", top=0, left=4*cm, style={"fontName": "Helvetica-Bold"}),
                    ],
                    borders={
                        "top": True,
                        "left": True,
                        "right": True
                    },
                ),
                detail_band=ReportBand(
                    height=0.5 * cm,
                    elements=[
                        ObjectValue(attribute_name="item_id",
                                    top=0,
                                    left=0.2 * cm),
                        ObjectValue(attribute_name="quantity",
                                    top=0,
                                    left=2 * cm),
                        #ObjectValue(attribute_name="unit_cost", top=0, left=4*cm),
                    ]),
            ),
        ]

    #report = MyReport(queryset=objects_list)
    report = MyReport(queryset=objects_list, db=db)
    report.generate_by(PDFGenerator, filename=output)

    output.seek(0)
    import gluon.contenttype
    response.headers["Content-Type"] = gluon.contenttype.contenttype(".pdf")
    filename = "%s_kits.pdf" % (request.env.server_name)
    response.headers[
        "Content-disposition"] = "attachment; filename=\"%s\"" % filename
    return output.read()
Пример #7
0
def kit_export_xls():
    """
        Export a list of Kits in Excel XLS format
        Sheet 1 is a list of Kits
        Then there is a separate sheet per kit, listing it's component items
    """

    try:
        import xlwt
    except ImportError:
        session.error = "xlwt module not available within the running Python - this needs installing for XLS output!"
        redirect(URL(c="kit"))

    from s3compat import StringIO
    output = StringIO()

    book = xlwt.Workbook()
    # List of Kits
    sheet1 = book.add_sheet("Kits")
    # Header row for Kits sheet
    row0 = sheet1.row(0)
    cell = 0
    table = db.budget_kit
    kits = db(table.id > 0).select()
    fields = [table[f] for f in table.fields if table[f].readable]
    for field in fields:
        row0.write(cell, field.label, xlwt.easyxf("font: bold True;"))
        cell += 1

    # For Header row on Items sheets
    table = db.budget_item
    fields_items = [table[f] for f in table.fields if table[f].readable]

    row = 1
    for kit in kits:
        # The Kit details on Sheet 1
        rowx = sheet1.row(row)
        row += 1
        cell1 = 0
        for field in fields:
            tab, col = str(field).split(".")
            rowx.write(cell1, kit[col])
            cell1 += 1
        # Sheet per Kit detailing constituent Items
        # Replace characters which are illegal in sheetnames
        sheetname = kit.code.replace("/", "_")
        sheet = book.add_sheet(sheetname)
        # Header row for Items sheet
        row0 = sheet.row(0)
        cell = 0
        for field_item in fields_items:
            row0.write(cell, field_item.label, xlwt.easyxf("font: bold True;"))
            cell += 1
        # List Items in each Kit
        table = db.budget_kit_item
        contents = db(table.kit_id == kit.id).select()
        rowy = 1
        for content in contents:
            table = db.budget_item
            item = db(table.id == content.item_id).select().first()
            rowx = sheet.row(rowy)
            rowy += 1
            cell = 0
            for field_item in fields_items:
                tab, col = str(field_item).split(".")
                # Do lookups for option fields
                if col == "cost_type":
                    opt = item[col]
                    value = str(budget_cost_type_opts[opt])
                elif col == "category_type":
                    opt = item[col]
                    value = str(budget_category_type_opts[opt])
                else:
                    value = item[col]
                rowx.write(cell, value)
                cell += 1

    book.save(output)

    output.seek(0)
    import gluon.contenttype
    response.headers["Content-Type"] = gluon.contenttype.contenttype(".xls")
    filename = "%s_kits.xls" % (request.env.server_name)
    response.headers[
        "Content-disposition"] = "attachment; filename=\"%s\"" % filename
    return output.read()