data_mover.py 4.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import xlrd3 as xlrd
  2. from openpyxl import load_workbook
  3. class Writer:
  4. """
  5. This class is made to update existing excel file.
  6. First it will open the file in python and then we can do multiple writes and once everything is update we can use
  7. save method in order to save the updated excel file. Hence, this class is very useful is saving time while updating
  8. excel files.
  9. """
  10. def __init__(self, path, sheet):
  11. self.path = path
  12. self.sht = sheet
  13. self.workbook = load_workbook(self.path)
  14. self.sheet = self.workbook[self.sht]
  15. def write(self, row, col, data):
  16. # Update the values using row and col number.
  17. # Note :- We are using openpyxl so row & column index will start from 1 instead of 0
  18. self.sheet.cell(row, col).value = data
  19. def save(self):
  20. # Call this method to save the file once every updates are written
  21. self.workbook.save(self.path)
  22. class Mover:
  23. """
  24. This class is used to copy data from one excel file to another. We can also use some filters to copy only targeted
  25. data.
  26. """
  27. def __init__(self, source_file_path, source_sheet, destination_file_path, destination_sheet, lines=0):
  28. """
  29. :param source_file_path: Path with filename of source excel file
  30. :param source_sheet: Sheet name of the source
  31. :param destination_file_path: Path with filename of Destination excel file
  32. :param destination_sheet: Sheet name of the destination
  33. :param lines: Number of lines starting from 1 to be considered for moving from source.
  34. """
  35. self.source_file_path = source_file_path
  36. self.source_sheet = source_sheet
  37. self.destination_file_path = destination_file_path
  38. self.destination_sheet = destination_sheet
  39. self.lines = lines
  40. def move(self, filters={}, add_missing_columns=False):
  41. source = self.read_xlsx(self.source_file_path, self.source_sheet)
  42. destination = self.read_xlsx(self.destination_file_path, self.destination_sheet)
  43. destination_wb = Writer(self.destination_file_path, self.destination_sheet) # Writer class object used to update existing file
  44. if add_missing_columns:
  45. self.add_missing_columns(source, destination, destination_wb)
  46. # again opening destination file as it is updated with the source file columns
  47. destination = self.read_xlsx(self.destination_file_path, self.destination_sheet)
  48. end = self.lines or source.nrows # if number of rows to be considered from source is not predefined the take all
  49. new_data = [source.row(row) for row in range(1, end)] # create a new list of all data and remove the filtered data
  50. remove_data = [] # rows not matching filter are stored here which is used later to remove data from new_data
  51. for filter in filters: # iterate through the dictionary of filter and
  52. ind = [x.value for x in source.row(0)].index(filter) # getting index of filter header then use the same index to check data
  53. for row in new_data:
  54. if row[ind].value != filters[filter]: # check if data is matching with filter
  55. remove_data.append(row)
  56. for row in remove_data: # removing unmatched data from new_data list
  57. new_data.remove(row)
  58. row_num = destination.nrows # used to maintain new row number
  59. for data in new_data: # iterating through the data to be written and writing then on the correct cells
  60. row_num += 1
  61. for cell in range(len(data)):
  62. try:
  63. # getting column number where new data is to be written with the help of indexing header in destination file
  64. ind = [x.value for x in destination.row(0)].index(source.row(0)[cell].value) + 1
  65. except ValueError:
  66. # if add_missing_columns is false then ValueError is thrown for the headers which are not present in destination
  67. continue
  68. destination_wb.write(row_num, ind, data[cell].value)
  69. destination_wb.save()
  70. def read_xlsx(self, path, sheet):
  71. # reading xlsx file using xlrd
  72. wb = xlrd.open_workbook(path)
  73. sht = wb.sheet_by_name(sheet)
  74. return sht
  75. def add_missing_columns(self, source, destination, destination_wb):
  76. # looking for the headers which are not present in destination file and then updating destination file
  77. source_headers = [x.value for x in source.row(0)]
  78. destination_headers = [x.value for x in destination.row(0)]
  79. col = len(destination_headers)
  80. for headers in source_headers:
  81. if headers not in destination_headers:
  82. col += 1
  83. destination_wb.write(1, col, headers)
  84. destination_wb.save()