def series_prepare_matrix(series_id, series, logo, langDict, justified=False): """ Helper function for series_export_formatted() """ ###################################################################### # # Get the data # ============ # * The sections within the template # * The layout rules for each question ###################################################################### # Check that the series_id has been passed in if len(request.args) != 1: output = s3_rest_controller(module, "series", rheader=s3db.survey_series_rheader) return output series_id = request.args[0] template = s3db.survey_getTemplateFromSeries(series_id) template_id = template.id sectionList = s3db.survey_getAllSectionsForSeries(series_id) title = "%s (%s)" % (series.name, template.name) title = survey_T(title, langDict) layout = [] survey_getQstnLayoutRules = s3db.survey_getQstnLayoutRules for section in sectionList: sectionName = survey_T(section["name"], langDict) rules = survey_getQstnLayoutRules(template_id, section["section_id"]) layoutRules = [sectionName, rules] layout.append(layoutRules) widgetList = s3db.survey_getAllWidgetsForTemplate(template_id) layoutBlocks = LayoutBlocks() ###################################################################### # # Store the questions into a matrix based on the layout and the space # required for each question - for example an option question might # need one row for each possible option, and if this is in a layout # then the position needs to be recorded carefully... # ###################################################################### preliminaryMatrix = getMatrix( title, logo, series, layout, widgetList, False, langDict, showSectionLabels=False, layoutBlocks=layoutBlocks ) if not justified: return preliminaryMatrix ###################################################################### # Align the questions so that each row takes up the same space. # This is done by storing resize and margin instructions with # each widget that is being printed ###################################################################### layoutBlocks.align() ###################################################################### # Now rebuild the matrix with the spacing for each widget set up so # that the document will be fully justified ###################################################################### layoutBlocks = LayoutBlocks() (matrix1, matrix2) = getMatrix(title, logo, series, layout, widgetList, True, langDict, showSectionLabels=False) return (matrix1, matrix2)
def series_prepare_matrix(series_id, series, logo, langDict, justified = False): module = "survey" resourcename = "series" tablename = "%s_%s" % (module, resourcename) s3mgr.load("survey_series") crud_strings = response.s3.crud_strings[tablename] ###################################################################### # # Get the data # ============ # * The sections within the template # * The layout rules for each question ###################################################################### # Check that the series_id has been passed in if len(request.args) != 1: output = s3_rest_controller(module, resourcename, rheader=response.s3.survey_series_rheader) return output series_id = request.args[0] template = response.s3.survey_getTemplateFromSeries(series_id) template_id = template.id sectionList = response.s3.survey_getAllSectionsForSeries(series_id) title = "%s (%s)" % (series.name, template.name) title = survey_T(title, langDict) layout = [] for section in sectionList: sectionName = survey_T(section["name"], langDict) rules = response.s3.survey_getQstnLayoutRules(template_id, section["section_id"] ) layoutRules = [sectionName, rules] layout.append(layoutRules) widgetList = response.s3.survey_getAllWidgetsForTemplate(template_id) layoutBlocks = LayoutBlocks() ###################################################################### # # Store the questions into a matrix based on the layout and the space # required for each question - for example an option question might # need one row for each possible option, and if this is in a layout # then the position needs to be recorded carefully... # ###################################################################### preliminaryMatrix = getMatrix(title, logo, series, layout, widgetList, False, langDict, showSectionLabels = False, layoutBlocks = layoutBlocks ) # print >> sys.stdout, "preliminaryMatrix layoutBlocks" # print >> sys.stdout, layoutBlocks if not justified: return preliminaryMatrix ###################################################################### # Align the questions so that each row takes up the same space. # This is done by storing resize and margin instructions with # each widget that is being printed ###################################################################### layoutBlocks.align() # print >> sys.stdout, "Aligned layoutBlocks" # print >> sys.stdout, layoutBlocks ###################################################################### # Now rebuild the matrix with the spacing for each widget set up so # that the document will be fully justified ###################################################################### layoutBlocks = LayoutBlocks() (matrix1, matrix2) = getMatrix(title, logo, series, layout, widgetList, True, langDict, showSectionLabels = False, ) # f = open("/home/graeme/web2py/applications/eden/uploads/debug.txt","w+") # print >> f, matrix1 return (matrix1, matrix2)
def series_prepare_matrix(series_id, series, logo, langDict, justified=False): """ Helper function for series_export_formatted() """ ###################################################################### # # Get the data # ============ # * The sections within the template # * The layout rules for each question ###################################################################### # Check that the series_id has been passed in if len(request.args) != 1: output = s3_rest_controller(module, "series", rheader=s3db.survey_series_rheader) return output series_id = request.args[0] template = s3db.survey_getTemplateFromSeries(series_id) template_id = template.id sectionList = s3db.survey_getAllSectionsForSeries(series_id) title = "%s (%s)" % (series.name, template.name) title = survey_T(title, langDict) layout = [] survey_getQstnLayoutRules = s3db.survey_getQstnLayoutRules for section in sectionList: sectionName = survey_T(section["name"], langDict) rules = survey_getQstnLayoutRules(template_id, section["section_id"]) layoutRules = [sectionName, rules] layout.append(layoutRules) widgetList = s3db.survey_getAllWidgetsForTemplate(template_id) layoutBlocks = LayoutBlocks() ###################################################################### # # Store the questions into a matrix based on the layout and the space # required for each question - for example an option question might # need one row for each possible option, and if this is in a layout # then the position needs to be recorded carefully... # ###################################################################### preliminaryMatrix = getMatrix(title, logo, series, layout, widgetList, False, langDict, showSectionLabels=False, layoutBlocks=layoutBlocks) if not justified: return preliminaryMatrix ###################################################################### # Align the questions so that each row takes up the same space. # This is done by storing resize and margin instructions with # each widget that is being printed ###################################################################### layoutBlocks.align() ###################################################################### # Now rebuild the matrix with the spacing for each widget set up so # that the document will be fully justified ###################################################################### layoutBlocks = LayoutBlocks() (matrix1, matrix2) = getMatrix( title, logo, series, layout, widgetList, True, langDict, showSectionLabels=False, ) return (matrix1, matrix2)
def series_export_formatted(): prefix = "survey" resourcename = "series" tablename = "%s_%s" % (prefix, resourcename) s3mgr.load(tablename) crud_strings = response.s3.crud_strings[tablename] try: import xlwt except ImportError: output = s3_rest_controller(prefix, resourcename, rheader=response.s3.survey_series_rheader) return output fixedWidth = True cellWidth = 480 # 2 * 240 ###################################################################### # # Get the data # ============ # * The sections within the template # * The layout rules for each question ###################################################################### # Check that the series_id has been passed in if len(request.args) != 1: output = s3_rest_controller(prefix, resourcename, rheader=response.s3.survey_series_rheader) return output series_id = request.args[0] # Get the translation dictionary langDict = dict() if "translationLanguage" in request.post_vars: lang = request.post_vars.translationLanguage if lang == "Default": langDict = dict() else: try: lang_fileName = "applications/%s/uploads/survey/translations/%s.py" % (request.application, lang) langDict = read_dict(lang_fileName) except: langDict = dict() template = response.s3.survey_getTemplateFromSeries(series_id) template_id = template.id series = response.s3.survey_getSeries(series_id) sectionList = response.s3.survey_getAllSectionsForSeries(series_id) title = "%s (%s)" % (series.name, template.name) title = survey_T(title, langDict) layout = [] for section in sectionList: sectionName = survey_T(section["name"], langDict) rules = response.s3.survey_getQstnLayoutRules(template_id, section["section_id"] ) layoutRules = [sectionName, rules] layout.append(layoutRules) logo = os.path.join(request.folder, "static", "img", "logo", series.logo ) if not os.path.exists(logo) or not os.path.isfile(logo): logo = None widgetList = response.s3.survey_getAllWidgetsForTemplate(template_id) layoutBlocks = LayoutBlocks() preliminaryMatrix = getMatrix(title, logo, series, layout, widgetList, False, langDict, showSectionLabels = False, layoutBlocks = layoutBlocks ) if DEBUG: # print >> sys.stdout, preliminaryMatrix print >> sys.stdout, "preliminaryMatrix layoutBlocks" print >> sys.stdout, layoutBlocks layoutBlocks.align() if DEBUG: print >> sys.stdout, "Aligned layoutBlocks" print >> sys.stdout, layoutBlocks layoutBlocks = LayoutBlocks() (matrix1, matrix2) = getMatrix(title, logo, series, layout, widgetList, True, langDict, showSectionLabels = False, # layoutBlocks = layoutBlocks ) # if DEBUG: # print >> sys.stdout, "formattedMatrix" # print >> sys.stdout, formattedMatrix # print >> sys.stdout, "formattedMatrix layoutBlocks" # print >> sys.stdout, layoutBlocks #f = open("/home/graeme/web2py/applications/eden/uploads/debug.txt","w+") #print >> f, matrix1 matrix = matrix1 matrixAnswers = matrix2 ###################################################################### # # Store the questions into a matrix based on the layout and the space # required for each question - for example an option question might # need one row for each possible option, and if this is in a layout # then the position needs to be recorded carefully... # ###################################################################### # def processRule(rules, row, col, # matrix, matrixAnswer, action="rows"): # startcol = col # startrow = row # endcol = col # endrow = row # nextrow = row # nextcol = col # for element in rules: # if action == "rows": # row = endrow # col = startcol # elif action == "columns": # row = startrow # if endcol == 0: # col = 0 # else: # col = endcol+1 # # If the rule is a list then step through each element # if isinstance(element,list): # if action == "rows": # tempAction = "columns" # else: # tempAction = "rows" # (endrow, endcol) = processRule(element, row, col, # matrix, matrixAnswer, tempAction) # elif isinstance(element,dict): # (endrow, endcol) = processDict(element, row, col, # matrix, matrixAnswer, action) # else: # (endrow, endcol) = addData(element, row, col, # matrix, matrixAnswer) # if endrow > nextrow: # nextrow = endrow # if endcol > nextcol: # nextcol = endcol # return (nextrow, nextcol) # # def processDict(rules, row, col, # matrix, matrixAnswer, action="rows"): # startcol = col # startrow = row # nextrow = row # nextcol = col # for (key, value) in rules.items(): # if (key == "heading"): # cell = MatrixElement(row,col,value, style="styleSubHeader") # cell.merge(horizontal=1) # try: # matrix.addElement(cell) # except Exception as msg: # print msg # return (row,col) # endrow = row + 1 # endcol = col + 2 # elif (key == "rows") or (key == "columns"): # (endrow, endcol) = processRule(value, row, col, # matrix, matrixAnswer, action=key) # else: # ## Unknown key # continue # if action == "rows": # row = startrow # col = endcol + 1 # Add a blank column # elif action == "columns": # row = endrow # col = startcol # if endrow > nextrow: # nextrow = endrow # if endcol > nextcol: # nextcol = endcol # return (nextrow, nextcol) # # def addData(qstn, row, col, matrix, matrixAnswer): # question = response.s3.survey_getQuestionFromCode(qstn, series_id) # if question == {}: # return (row,col) # widgetObj = survey_question_type[question["type"]](question_id = question["qstn_id"]) # try: # (endrow, endcol) = widgetObj.writeToMatrix(matrix, # row, # col, # answerMatrix=matrixAnswer, # langDict = langDict # ) # except Exception as msg: # print >> sys.stderr, msg # return (row,col) # if question["type"] == "Grid": # matrix.boxRange(row, col, endrow-1, endcol-1) # return (endrow, endcol) # matrix = DataMatrix() # matrixAnswers = DataMatrix() # template = response.s3.survey_getTemplateFromSeries(series_id) # series = response.s3.survey_getSeries(series_id) # logo = os.path.join(request.folder, # "static", # "img", # "logo", # series.logo # ) # if os.path.exists(logo) and os.path.isfile(logo): # cell = MatrixElement(0,col,"", style=["styleText"]) # cell.merge(vertical=2) # matrix.addElement(cell) # col = 2 # row += 1 # else: # logo = None # title = "%s (%s)" % (series.name, template.name) # title = survey_T(title, langDict) # cell = MatrixElement(0, col, title, style="styleHeader") # cell.merge(vertical=1, horizontal=len(title)) # matrix.addElement(cell) # row += 2 # for section in sectionList: # col = 0 # row += 1 # rules = layout[section["name"]] # cell = MatrixElement(row, col, survey_T(section["name"], langDict), # style="styleHeader") # try: # matrix.addElement(cell) # except Exception as msg: # print >> sys.stderr, msg # row += 1 # startrow = row # (row, col) = processRule(rules, row, col, matrix, matrixAnswers) # matrix.boxRange(startrow, 0, row, col-1) ###################################################################### # # Now take the matrix data type and generate a spreadsheet from it # ###################################################################### import math def wrapText(sheet, cell, style): row = cell.row col = cell.col try: text = unicode(cell.text) except: text = cell.text width = 16 # Wrap text and calculate the row width and height characters_in_cell = float(width-2) twips_per_row = 255 #default row height for 10 point font if cell.merged(): try: sheet.write_merge(cell.row, cell.row + cell.mergeV, cell.col, cell.col + cell.mergeH, text, style ) except Exception as msg: print >> sys.stderr, msg print >> sys.stderr, "row: %s + vert: %s, col: %s + horiz %s" % (cell.row, cell.mergeV, cell.col, cell.mergeH) posn = "%s,%s"%(cell.row, cell.col) if matrix.matrix[posn]: print >> sys.stderr, matrix.matrix[posn] rows = math.ceil((len(text) / characters_in_cell) / (1 + cell.mergeH)) else: sheet.write(cell.row, cell.col, text, style ) rows = math.ceil(len(text) / characters_in_cell) new_row_height = int(rows * twips_per_row) new_col_width = width * COL_WIDTH_MULTIPLIER if sheet.row(row).height < new_row_height: sheet.row(row).height = new_row_height if sheet.col(col).width < new_col_width: sheet.col(col).width = new_col_width def mergeStyles(listTemplate, styleList): """ Take a list of styles and return a single style object with all the differences from a newly created object added to the resultant style. """ if len(styleList) == 0: finalStyle = xlwt.XFStyle() elif len(styleList) == 1: finalStyle = listTemplate[styleList[0]] else: zeroStyle = xlwt.XFStyle() finalStyle = xlwt.XFStyle() for i in range(0,len(styleList)): finalStyle = mergeObjectDiff(finalStyle, listTemplate[styleList[i]], zeroStyle) return finalStyle def mergeObjectDiff(baseObj, newObj, zeroObj): """ function to copy all the elements in newObj that are different from the zeroObj and place them in the baseObj """ elementList = newObj.__dict__ for (element, value) in elementList.items(): try: baseObj.__dict__[element] = mergeObjectDiff(baseObj.__dict__[element], value, zeroObj.__dict__[element]) except: if zeroObj.__dict__[element] != value: baseObj.__dict__[element] = value return baseObj COL_WIDTH_MULTIPLIER = 240 book = xlwt.Workbook(encoding="utf-8") output = StringIO() protection = xlwt.Protection() protection.cell_locked = 1 noProtection = xlwt.Protection() noProtection.cell_locked = 0 borders = xlwt.Borders() borders.left = xlwt.Borders.DOTTED borders.right = xlwt.Borders.DOTTED borders.top = xlwt.Borders.DOTTED borders.bottom = xlwt.Borders.DOTTED borderT1 = xlwt.Borders() borderT1.top = xlwt.Borders.THIN borderT2 = xlwt.Borders() borderT2.top = xlwt.Borders.MEDIUM borderL1 = xlwt.Borders() borderL1.left = xlwt.Borders.THIN borderL2 = xlwt.Borders() borderL2.left = xlwt.Borders.MEDIUM borderR1 = xlwt.Borders() borderR1.right = xlwt.Borders.THIN borderR2 = xlwt.Borders() borderR2.right = xlwt.Borders.MEDIUM borderB1 = xlwt.Borders() borderB1.bottom = xlwt.Borders.THIN borderB2 = xlwt.Borders() borderB2.bottom = xlwt.Borders.MEDIUM alignBase = xlwt.Alignment() alignBase.horz = xlwt.Alignment.HORZ_LEFT alignBase.vert = xlwt.Alignment.VERT_TOP alignWrap = xlwt.Alignment() alignWrap.horz = xlwt.Alignment.HORZ_LEFT alignWrap.vert = xlwt.Alignment.VERT_TOP alignWrap.wrap = xlwt.Alignment.WRAP_AT_RIGHT shadedFill = xlwt.Pattern() shadedFill.pattern = xlwt.Pattern.SOLID_PATTERN shadedFill.pattern_fore_colour = 0x16 # 25% Grey shadedFill.pattern_back_colour = 0x08 # Black headingFill = xlwt.Pattern() headingFill.pattern = xlwt.Pattern.SOLID_PATTERN headingFill.pattern_fore_colour = 0x1F # ice_blue headingFill.pattern_back_colour = 0x08 # Black styleTitle = xlwt.XFStyle() styleTitle.font.height = 0x0140 # 320 twips, 16 points styleTitle.font.bold = True styleTitle.alignment = alignBase styleHeader = xlwt.XFStyle() styleHeader.font.height = 0x00F0 # 240 twips, 12 points styleHeader.font.bold = True styleHeader.alignment = alignBase styleSubHeader = xlwt.XFStyle() styleSubHeader.font.bold = True styleSubHeader.alignment = alignWrap styleSectionHeading = xlwt.XFStyle() styleSectionHeading.font.bold = True styleSectionHeading.alignment = alignWrap styleSectionHeading.pattern = headingFill styleHint = xlwt.XFStyle() styleHint.protection = protection styleHint.font.height = 160 # 160 twips, 8 points styleHint.font.italic = True styleHint.alignment = alignWrap styleText = xlwt.XFStyle() styleText.protection = protection styleText.alignment = alignWrap styleInstructions = xlwt.XFStyle() styleInstructions.font.height = 0x00B4 # 180 twips, 9 points styleInstructions.font.italic = True styleInstructions.protection = protection styleInstructions.alignment = alignWrap styleBox = xlwt.XFStyle() styleBox.borders = borders styleBox.protection = noProtection styleInput = xlwt.XFStyle() styleInput.borders = borders styleInput.protection = noProtection styleInput.pattern = shadedFill boxL1 = xlwt.XFStyle() boxL1.borders = borderL1 boxL2 = xlwt.XFStyle() boxL2.borders = borderL2 boxT1 = xlwt.XFStyle() boxT1.borders = borderT1 boxT2 = xlwt.XFStyle() boxT2.borders = borderT2 boxR1 = xlwt.XFStyle() boxR1.borders = borderR1 boxR2 = xlwt.XFStyle() boxR2.borders = borderR2 boxB1 = xlwt.XFStyle() boxB1.borders = borderB1 boxB2 = xlwt.XFStyle() boxB2.borders = borderB2 styleList = {} styleList["styleTitle"] = styleTitle styleList["styleHeader"] = styleHeader styleList["styleSubHeader"] = styleSubHeader styleList["styleSectionHeading"] = styleSectionHeading styleList["styleHint"] = styleHint styleList["styleText"] = styleText styleList["styleInstructions"] = styleInstructions styleList["styleInput"] = styleInput styleList["boxL1"] = boxL1 styleList["boxL2"] = boxL2 styleList["boxT1"] = boxT1 styleList["boxT2"] = boxT2 styleList["boxR1"] = boxR1 styleList["boxR2"] = boxR2 styleList["boxB1"] = boxB1 styleList["boxB2"] = boxB2 sheet1 = book.add_sheet(T("Assessment")) sheetA = book.add_sheet(T("Metadata")) maxCol = 0 for cell in matrix.matrix.values(): if cell.col + cell.mergeH > maxCol: maxCol = cell.col + cell.mergeH if cell.joined(): continue style = mergeStyles(styleList, cell.styleList) if (style.alignment.wrap == style.alignment.WRAP_AT_RIGHT): # get all the styles from the joined cells # and merge these styles in. joinedStyles = matrix.joinedElementStyles(cell) joinedStyle = mergeStyles(styleList, joinedStyles) try: wrapText(sheet1, cell, joinedStyle) except: pass else: if cell.merged(): # get all the styles from the joined cells # and merge these styles in. joinedStyles = matrix.joinedElementStyles(cell) joinedStyle = mergeStyles(styleList, joinedStyles) try: sheet1.write_merge(cell.row, cell.row + cell.mergeV, cell.col, cell.col + cell.mergeH, unicode(cell.text), joinedStyle ) except Exception as msg: print >> sys.stderr, msg print >> sys.stderr, "row: %s + vert: %s, col: %s + horiz %s" % (cell.row, cell.mergeV, cell.col, cell.mergeH) posn = "%s,%s"%(cell.row, cell.col) if matrix.matrix[posn]: print >> sys.stderr, matrix.matrix[posn] else: sheet1.write(cell.row, cell.col, unicode(cell.text), style ) if fixedWidth: for col in range(maxCol+1): sheet1.col(col).width = cellWidth sheetA.write(0, 0, "Question Code") sheetA.write(0, 1, "Response Count") sheetA.write(0, 2, "Values") sheetA.write(0, 3, "Cell Address") for cell in matrixAnswers.matrix.values(): style = mergeStyles(styleList, cell.styleList) sheetA.write(cell.row, cell.col, unicode(cell.text), style ) if logo != None: sheet1.insert_bitmap(logo, 0, 0) sheet1.protect = True sheetA.protect = True # for i in range(26): # sheetA.col(i).width = 0 sheetA.write(0, 26, unicode(T("Please do not remove this sheet")), styleHeader ) sheetA.col(26).width = 12000 book.save(output) output.seek(0) response.headers["Content-Type"] = contenttype(".xls") seriesName = response.s3.survey_getSeriesName(series_id) filename = "%s.xls" % seriesName response.headers["Content-disposition"] = "attachment; filename=\"%s\"" % filename return output.read()