Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XlsxWriter: lock only specific cells

I'm creating xlsx files with xlsxwriter and want to protect specific cells (for example all cells in a range B2:B20). The documentation says that you can use worksheet.protect() method - it's turn on protection for whole worksheet by default - and then you can use workbook.add_format({'locked': 0}) for unlocking specific cells. But I want vice versa - I want to lock only specific range of cells and leave the rest of the worksheet unlocked. How can I do this?

like image 929
dabajabaza Avatar asked Nov 30 '16 09:11

dabajabaza


People also ask

How do I hide columns in XlsxWriter?

To hide specific rows or columns in a worksheet, set hidden parameter to 1 in set_row() or set_column() method. The following statement hides the columns C, D and E in the active worksheet.

Is XlsxWriter included in Python?

XlsxWriter is a Python module for writing files in the Excel 2007+ XLSX file format. XlsxWriter can be used to write text, numbers, formulas and hyperlinks to multiple worksheets and it supports features such as formatting and many more, including: 100% compatible Excel XLSX files.


2 Answers

The way to do this is the same as in Excel: set an unlock format for the entire sheet.

In Excel and XlsxWriter this translates to setting a unlock format for all the columns. Like this:

import xlsxwriter

workbook = xlsxwriter.Workbook('protection.xlsx')
worksheet = workbook.add_worksheet()

# Create some cell formats with protection properties.
unlocked = workbook.add_format({'locked': False})
locked   = workbook.add_format({'locked': True})

# Format the worksheet to unlock all cells.
worksheet.set_column('A:XDF', None, unlocked)

# Turn worksheet protection on.
worksheet.protect()

# Write a locked and an unlocked cell.
worksheet.write('B1', 'Cell A1 is locked. It cannot be edited.')
worksheet.write('B2', 'Cell A2 is unlocked. It can be edited.')
worksheet.write('B3', 'Cell A3 is unlocked. It can be edited.')

worksheet.write('A1', 'Hello', locked  )  
worksheet.write('A2', 'Hello', unlocked)
worksheet.write('A3', 'Hello'          ) # Unlocked by default.

workbook.close()
like image 60
jmcnamara Avatar answered Sep 23 '22 18:09

jmcnamara


You can use the following code to protect the specific range of cells for single or multi sheet excel file.

Note: this function assumes that the Excel file is already been generated.

def protectCell(excelFilePath, protectCellRange='a1:b1', sheetName = 'Sheet1'):
    ''' 
    To protect the range of cell in an Excel file.
    arguments:
        1. excelFilePath : path of excel file.
        2. protectCellRange : Range of cells to protect. default is a1:b1
        3. sheetName : name of the sheet present in Excel file. Default is Sheet1
        
        Currently it supports column from A to Z only. i.e 0 to 25 columns 
        
    '''
    protectCellRange = protectCellRange.lower() 
    temp = list(string.ascii_lowercase)
    # refer = {'a':0, 'b':1, 'c':2, 'd':3, 'e':4}
    refer = {}
    for i, item in enumerate(temp):
        refer[item] = i
        
    writer = pd.ExcelWriter(excelFilePath, engine='xlsxwriter')
    TotalDf = pd.read_excel(excelFilePath, sheet_name = None, header= None)
    for sheet in TotalDf.keys():
        if sheet == sheetName:
            df = TotalDf[sheetName]
            # workbook = xlsxwriter.Workbook('excelFilePath='./temp/protection.xlsx')
            # worksheet = workbook.add_worksheet()
            df.to_excel(writer, sheet_name = sheetName, header= False, index=False)
            workbook = writer.book
            worksheet = writer.sheets[sheetName]
            # Create some cell formats with protection properties.
            unlocked = workbook.add_format({'locked': False, 'font_size': 9, 'text_wrap': True, 'align': 'left', 'valign': 'top',})
            locked   = workbook.add_format({'locked': True, 'font_size': 9, 'text_wrap': True, 'align': 'left', 'valign': 'top',})
            
            # Format the worksheet to unlock all cells.
            worksheet.set_column('A:C', 20, unlocked)
            
            # Turn worksheet protection on.
            worksheet.protect()
            
            startPointer = protectCellRange.split(':')[0]
            endPointer = protectCellRange.split(':')[-1]
            
            if len(startPointer) < 1 or len(endPointer) < 1:
                print(f'Please specify correct cell range. Specified range is {protectCellRange}')
                return 'Failure'
            
            colRange = range(refer[startPointer[0]],refer[endPointer[0]] + 1 ) 
            rowRange = range(int(startPointer[1:]), int(endPointer[1:]) + 1 )
            for col in colRange:
                for row in rowRange:
                    c = [k for k,v in refer.items() if v == col][0].upper()
                    print(col,row)
                    try:
                        value = df[col].iloc[row-1]
                        #print(f'value is ::: {value}')
                        worksheet.write(c+str(row), value, locked, )
                    except:
                        print(f'exception in Cell: {c+str(row)}')
        else:
            df = TotalDf[sheet]
            df.to_excel(writer,sheet_name = sheet, header= False, index=False)
            workbook = writer.book
            worksheet = writer.sheets[sheet]
            wrap_format = workbook.add_format({'text_wrap': True, 'align': 'left', 'valign': 'top'})
            worksheet.set_column('A:E', 20, wrap_format)
    workbook.worksheets_objs.sort(key=lambda x: x.name)    
    writer.save()
    writer.close()  
    workbook.close()
    print(f'Excel File is protected for section {protectCellRange}')
    return 'Success'

#===========================================================================

Call the function with all the required parameters

protectCell(excelFilePath='./Cell_protection.xlsx',
            protectCellRange = 'A4:C7', sheetName = 'ABC')

enter image description here

protectCell(excelFilePath='./Cell_protection.xlsx',
                protectCellRange = 'A4:', sheetName = 'ABC')
#Range is not mentioned properly 

enter image description here

protectCell(excelFilePath='./Cell_protection.xlsx',
                    protectCellRange = ':C7', sheetName = 'ABC')
#Range is not mentioned properly

enter image description here

like image 39
Vaibhav K Avatar answered Sep 24 '22 18:09

Vaibhav K