Creates .xlsx reports using xlsxwriter

def reporter(self):
        """
        Creates .xlsx reports using xlsxwriter
        """
        # Create a workbook to store the report. Using xlsxwriter rather than a simple csv format, as I want to be
        # able to have appropriately sized, multi-line cells
        workbook = xlsxwriter.Workbook(os.path.join(self.reportpath, '{}.xlsx'.format(self.analysistype)))
        # New worksheet to store the data
        worksheet = workbook.add_worksheet()
        # Add a bold format for header cells. Using a monotype font size 10
        bold = workbook.add_format({'bold': True, 'font_name': 'Courier New', 'font_size': 10})
        # Format for data cells. Monotype, size 10, top vertically justified
        courier = workbook.add_format({'font_name': 'Courier New', 'font_size': 10})
        courier.set_align('top')
        # Initialise the position within the worksheet to be (0,0)
        row = 0
        # A dictionary to store the column widths for every header
        columnwidth = dict()
        for sample in self.metadata:
            # Reset the column to zero
            col = 0
            # Initialise a list to store all the data for each strain
            data = list()
            # Initialise a list of all the headers with 'Strain'
            headers = ['Strain']
            if sample[self.analysistype].targetnames != 'NA':
                # Append the sample name to the data list only if the script could find targets
                data.append(sample.name)
                if sample[self.analysistype].blastresults != 'NA':
                    for target in sorted(sample[self.analysistype].targetnames):
                        # Add the name of the gene to the header
                        headers.append(target)
                        try:
                            # Append the percent identity to the data list
                            data.append(str(sample[self.analysistype].blastresults[target]))
                            # Only if the alignment option is selected, for inexact results, add alignments
                            if self.align and sample[self.analysistype].blastresults[target] != 100.00:
                                # Align the protein (and nucleotide) sequences to the reference
                                self.alignprotein(sample, target)
                                # Add the appropriate headers
                                headers.extend(['{}_aa_Identity'.format(target),
                                                '{}_aa_Alignment'.format(target),
                                                '{}_aa_SNP_location'.format(target),
                                                '{}_nt_Alignment'.format(target),
                                                '{}_nt_SNP_location'.format(target)
                                                ])
                                # Add the alignment, and the location of mismatches for both nucleotide and amino
                                # acid sequences
                                data.extend([sample[self.analysistype].aaidentity[target],
                                             sample[self.analysistype].aaalign[target],
                                             sample[self.analysistype].aaindex[target],
                                             sample[self.analysistype].ntalign[target],
                                             sample[self.analysistype].ntindex[target],
                                             ])
                        # If there are no blast results for the target, add a '-'
                        except (KeyError, TypeError):
                            data.append('-')
                        # If there are no blast results at all, add a '-'
                        else:
                            data.append('-')
            # Write the header to the spreadsheet
            for header in headers:
                worksheet.write(row, col, header, bold)
                # Set the column width based on the longest header
                try:
                    columnwidth[col] = len(header)if len(header) > columnwidth[col] else columnwidth[col]
                except KeyError:
                    columnwidth[col] = len(header)
                worksheet.set_column(col, col, columnwidth[col])
                col += 1
            # Increment the row and reset the column to zero in preparation of writing results
            row += 1
            col = 0
            # List of the number of lines for each result
            totallines = list()
            # Write out the data to the spreadsheet
            for results in data:
                worksheet.write(row, col, results, courier)
                try:
                    # Counting the length of multi-line strings yields columns that are far too wide, only count
                    # the length of the string up to the first line break
                    alignmentcorrect = len(results.split('\n')[0])
                    # Count the number of lines for the data
                    lines = results.count('\n') if results.count('\n') >= 1 else 1
                    # Add the number of lines to the list
                    totallines.append(lines)
                # If there are no newline characters, set the width to the length of the string
                except AttributeError:
                    alignmentcorrect = len(results)
                    lines = 1
                    # Add the number of lines to the list
                    totallines.append(lines)
                # Increase the width of the current column, if necessary
                try:
                    columnwidth[col] = alignmentcorrect if alignmentcorrect > columnwidth[col] else columnwidth[col]
                except KeyError:
                    columnwidth[col] = alignmentcorrect
                worksheet.set_column(col, col, columnwidth[col])
                col += 1
            # Set the width of the row to be the number of lines (number of newline characters) * 12
            if len(totallines) != 0:
                worksheet.set_row(row, max(totallines) * 12)
            else:
                worksheet.set_row(row, 1)
            # Increase the row counter for the next strain's data
            row += 1
        # Close the workbook
        workbook.close()