-
-
Save SteveDevOps/d218d937629b575a42ee469ba661c7f7 to your computer and use it in GitHub Desktop.
Revisions
-
SteveDevOps revised this gist
Feb 4, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,7 +14,7 @@ #For RGB30.. #I installed xlsxwriter local on sys76 laptop instead using github method from original author / PREREQ above #then I turned on ssh on device and scp'ed down the es_systems.cfg to a new local /etc/emulationstation dir #I had to also fix fmt calls as they were not compatible with current xlsxwriter #ref: https://github.com/jmcnamara/XlsxWriter/issues/633 #and finally I had to mount the roms sdcard to same path as seen by rocknix firemware : /storage -
SteveDevOps revised this gist
Feb 4, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -19,7 +19,7 @@ #ref: https://github.com/jmcnamara/XlsxWriter/issues/633 #and finally I had to mount the roms sdcard to same path as seen by rocknix firemware : /storage #local setup: ~/projects/gamelist #I just ran export.py -d from that folder # -*- coding: utf-8 -*- import xml.etree.ElementTree as et -
SteveDevOps revised this gist
Feb 4, 2025 . 1 changed file with 50 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,6 +12,14 @@ #RUN saved gist script #python3 export.py /userdata/roms/export_list.xlsx #For RGB30.. #I installed xlsxwriter local on sys76 laptop instead using github method from original author / PREREQ above #then I scp'ed down the es_systems.cfg to a new local /etc/emulationstation dir #I had to also fix fmt calls as they were not compatible with current xlsxwriter #ref: https://github.com/jmcnamara/XlsxWriter/issues/633 #and finally I had to mount the roms sdcard to same path as seen by rocknix firemware : /storage #local setup: ~/projects/gamelist # -*- coding: utf-8 -*- import xml.etree.ElementTree as et @@ -383,10 +391,35 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) wb.set_custom_property('Date Exported', dt.now()) #fmt_bold = wb.add_format({'bold': True}) #fmt_bold_2 = wb.add_format({'bold': True, 'bg_color': 'red', 'color': 'white'}) #fmt_sys_header = wb.add_format({'bold': True, 'bg_color': 'green', 'color': 'white'}) #fmt_fav_row = wb.add_format({'bg_color': '#FFCC7C'}) #setup formats explicitly fmt_bold_style = { 'bold': True, } fmt_bold_2_style = { 'bold': True, 'bg_color': 'red', 'fg_color': 'white', } fmt_sys_header_style = { 'bold': True, 'bg_color': 'green', 'fg_color': 'white', } fmt_fav_row_style = { 'bg_color': '#FFCC7C', } fmt_bold = wb.add_format(fmt_bold_style) fmt_bold_2 = wb.add_format(fmt_bold_2_style) fmt_sys_header = wb.add_format(fmt_sys_header_style) fmt_fav_row = wb.add_format(fmt_fav_row_style) # Add a summary sheet as the 1st sheet in the workbook start = wb.add_worksheet("Summary") @@ -405,7 +438,16 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) kid_sheet.set_tab_color('pink') custom_sheets = {} #if len(custom_collections)>0 : # logger.debug("Adding custom collections to export") # for collection in custom_collections: # if len(custom_collections[collection]) > 0: # logger.debug("Exporting custom collection %s", collection) # s = wb.add_worksheet(collection) # s.set_tab_color("gray") # custom_sheets[collection] = s # The table headers for the each system's sheet table_headers = list(map(lambda x: {'header': str(x).capitalize()}, Game.get_headers())) @@ -601,6 +643,7 @@ def parse_arguments(): logger.info("Total games after parsing gamelist files - " + str(total_games)) logger.info("Exporting to file %s",output) #xlsx_export_workbook(systems, output, collections) xlsx_export_workbook(systems, output) logger.debug("Finished") -
Steve Duys revised this gist
Mar 14, 2023 . 1 changed file with 4 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,12 +2,14 @@ #BATOCERA SETUP: #(removed custom game collection section, caused error in batocera) #wget -O export.py <this gist> #SETUP PREREQ: (I cloned repo on laptop first and scp'ed up to batocera box) #git clone --depth=1 https://github.com/jmcnamara/xlsxwriter #cd xlsxwriter #sudo python3 setup.py install #RUN saved gist script #python3 export.py /userdata/roms/export_list.xlsx -
Steve Duys revised this gist
Mar 14, 2023 . 1 changed file with 12 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,16 @@ #!/usr/bin/env python #BATOCERA SETUP: #(removed custom game collection section, caused error in batocera) #wget -O export.py <this gist> #git clone --depth=1 https://github.com/jmcnamara/xlsxwriter #cd xlsxwriter #sudo python3 setup.py install #RUN: #python3 export.py /userdata/roms/export_list.xlsx # -*- coding: utf-8 -*- import xml.etree.ElementTree as et import logging as log -
Steve Duys revised this gist
Mar 14, 2023 . 1 changed file with 1 addition and 10 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -391,16 +391,7 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) kid_sheet.set_tab_color('pink') custom_sheets = {} # The table headers for the each system's sheet table_headers = list(map(lambda x: {'header': str(x).capitalize()}, Game.get_headers())) -
cmitu revised this gist
Jan 29, 2021 . 1 changed file with 38 additions and 39 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -62,8 +62,7 @@ def get_xml_element_date(xml, node_name): Returns a DateTime or a String, depending on the value of the @parm node_name. """ ES_TIME_FORMAT = "%Y%m%dT%H%M%S" if not xml.find(node_name) is None and not xml.find(node_name).text is None: date_text = xml.find(node_name).text # Release date can appear as both ISO date or just as an year. @@ -195,7 +194,7 @@ def check_rom(rom_folder, rom_path): return os.path.isfile(path_to_check) or os.path.isdir(path_to_check) def get_rom_path(rom_folder, rom_path): path_to_check = rom_path; if not rom_path.startswith('/'): @@ -209,18 +208,18 @@ def get_roms_in_collection(rom_path_list, all_games): Produce a list of Game objects, from @rom_path - a list of ROM paths @all_games - a list of all Game objects. """ roms = [] for rom in all_games: if rom.info['realpath'] in rom_path_list: logger.debug("Found game %s at path %s", rom.info['name'], rom.info['realpath']) roms.append(rom) return roms def skip_system(system_name): return str(system_name).upper() in map(lambda x: x.upper(), skipped_systems) @@ -244,23 +243,24 @@ def parse_systems(): s = System(system) if s.info['path'] is None or s.info['name'] is None: logger.debug(u"System {0} has no path or name, skipping".format(s.info['fullname'])) continue if skip_system(s.info['name']): logger.info(u"System {0} is skipped as configured".format(s.info['fullname'])) continue # Try to open and parse the gamelist for this system. logger.debug(u"Analyzing system: %s (%s)",s.info['fullname'], s.info['name']) try: gamelist_path = get_gamelist(s.info['name'], s.info['path']) if gamelist_path is None: logger.debug("%s system has no gamelist, skipping",s.info['fullname']) continue logger.debug("Gamelist for %s is read from %s", s.info['name'], gamelist_path); gamelist = et.parse(gamelist_path) except IOError: logger.warn("Could not open the gamelist for " + s.info['name'] + ", skipping !") @@ -295,22 +295,22 @@ def parse_custom_collections(): Tries to find the custom ES defined collections, which should be under $HOME/.emulationstation/collections Each collection is a file named 'custom-XYZ.cfg', which contains a list of ROM paths. Open each .cfg file and read the list of paths. Return a dict containing - the collection name - the corresponging list of ROM paths. """ collections = {} logger.debug("Trying to find custom collections") custom_collections_folder = "{0}/.emulationstation/collections".format(os.environ['HOME']) if not os.path.isdir(custom_collections_folder): logger.info("No custom collection folder found, skipping") return for file in os.listdir(custom_collections_folder): cfg_path = custom_collections_folder + '/' + file; if fnmatch.fnmatch(file, 'custom-*.cfg') and os.path.isfile(cfg_path): collection_name = file.replace('custom-', '').replace('.cfg', '').capitalize() logger.info("Found collection %s", collection_name) @@ -330,11 +330,11 @@ def parse_custom_collections(): collections[collection_name] = list(map(lambda r: r.strip('\n'), roms)) except Exception: logger.warn("Cannot read collection file %s", file) return collections # Export the system list to excel def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None): @@ -349,8 +349,7 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) all_collection = System.get_collection('all') fav_collection = System.get_collection('favorite') kid_collection = System.get_collection('kid') # Create the Workbook wb = xlsxwriter.Workbook(output, {'default_date_format': 'dd-mm-yyyy', @@ -390,18 +389,18 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) kid_sheet = wb.add_worksheet("Kid Games") kid_sheet.set_tab_color('pink') custom_sheets = {} if len(custom_collections)>0 : logger.debug("Adding custom collections to export") for collection in custom_collections: if len(custom_collections[collection]) > 0: logger.debug("Exporting custom collection %s", collection) s = wb.add_worksheet(collection) s.set_tab_color("gray") custom_sheets[collection] = s # The table headers for the each system's sheet table_headers = list(map(lambda x: {'header': str(x).capitalize()}, Game.get_headers())) @@ -413,7 +412,7 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) # Create a table with each system and the # of games detected in each system. # Make the system column be a link to the sheet with the system games. start.write_url(i+1, 0, "internal:'" + s.info['name'] + "'!A1", string=u"{0} ({1})".format(s.info['fullname'], s.info['name']) ) start.write(i+1, 1, len(s.games)) @@ -475,13 +474,13 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) for (sheet, collection, name) in special_collections: sheet.set_column(0, 0, 20) # System column size sheet.set_column(1, 1, 50) # Game name column size # Check if the collection has any games at all before exporting it logger.debug("Special collection %s has %s games", name, len(collection.games)) if len(collection.games) < 1: logger.info("Special collection %s has no games, sheet will be empty", name) continue t = sheet.add_table(0, 0, len(collection.games), len(Game.get_headers()), { 'style': 'Table Style Light 9', @@ -496,21 +495,21 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) sheet.set_column('C:C', None, None, {'hidden': True}) sheet.set_column('I:I', 12) sheet.set_column('J:J', 12) # Write the Custom Collections for c in custom_sheets: logger.debug("Writing custom collection %s", c) # Produce a list of Game objects based on the paths of ROMs rom_list = get_roms_in_collection(custom_collections[c], all_collection.games) logger.debug("Should write %d games to %s collection", len(rom_list), c) # Ok, write the info in the custom collection worksheet s = custom_sheets[c] logger.debug("Adding custom collection in sheet %s", s.get_name()) s.set_column(0, 0, 20) # System column size s.set_column(1, 1, 50) # Game name column size t = s.add_table(0, 0, len(rom_list), len(Game.get_headers()), { 'style': 'Table Style Light 9', @@ -525,7 +524,7 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) s.set_column('C:C', None, None, {'hidden': True}) s.set_column('I:I', 12) s.set_column('J:J', 12) # Close the workbook wb.close() @@ -560,7 +559,7 @@ def xlsx_export_system_row(workbook, sheet, row_number, game, system_name=None): sheet.write(row_number, column + offset, game.info[header]) # If we're on the 'All' sheet, add the description of the game in the cell comments if sheet.get_name().lower() == "all" and header.lower() == "name" and not (game.info['desc'] is None or len(game.info['desc']) < 1): sheet.write_comment(row_number, column + offset, game.info['desc'], {'x_scale': 4, 'y_scale': 4}) @@ -590,13 +589,13 @@ def parse_arguments(): logger.debug("Starting") systems = parse_systems() collections = parse_custom_collections(); # See how many games we have total_games = sum(map(lambda system: len(system.games), systems)) logger.info("Total games after parsing gamelist files - " + str(total_games)) logger.info("Exporting to file %s",output) xlsx_export_workbook(systems, output, collections) logger.debug("Finished") -
cmitu revised this gist
Oct 3, 2018 . 1 changed file with 7 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -195,8 +195,9 @@ def check_rom(rom_folder, rom_path): return os.path.isfile(path_to_check) or os.path.isdir(path_to_check) def get_rom_path(rom_folder, rom_path): path_to_check = rom_path; if not rom_path.startswith('/'): path_to_check = rom_folder + "/" + rom_path @@ -313,7 +314,11 @@ def parse_custom_collections(): if fnmatch.fnmatch(file, 'custom-*.cfg') and os.path.isfile(cfg_path): collection_name = file.replace('custom-', '').replace('.cfg', '').capitalize() logger.info("Found collection %s", collection_name) if len(collection_name) > 31: logger.warn("Collection %s name too long, truncating to 31 chars", collection_name) collection_name = collection_name[:31] # OK, we have the file, open it and get it line by line try: cfg_file = open(cfg_path, "r") -
cmitu revised this gist
Oct 3, 2018 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -195,6 +195,8 @@ def check_rom(rom_folder, rom_path): return os.path.isfile(path_to_check) or os.path.isdir(path_to_check) def get_rom_path(rom_folder, rom_path): path_to_check = rom_path if not rom_path.startswith('/'): path_to_check = rom_folder + "/" + rom_path -
cmitu revised this gist
Sep 9, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -192,7 +192,7 @@ def check_rom(rom_folder, rom_path): if not rom_path.startswith('/'): path_to_check = rom_folder + "/" + rom_path return os.path.isfile(path_to_check) or os.path.isdir(path_to_check) def get_rom_path(rom_folder, rom_path): if not rom_path.startswith('/'): -
cmitu revised this gist
May 3, 2018 . 1 changed file with 13 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -253,7 +253,7 @@ def parse_systems(): try: gamelist_path = get_gamelist(s.info['name'], s.info['path']) logger.debug("Gamelist for %s is read from %s", s.info['name'], gamelist_path); if gamelist_path is None: logger.debug("%s system has no gamelist, skipping",s.info['fullname']) continue @@ -412,13 +412,21 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) # Print the table header b.set_column(0, 0, 50) # By default, don't add an auto-filter unless we have some records. auto_filter_v = False if len(s.games)>0: auto_filter_v = True t = b.add_table(0, 0, len(s.games), len(Game.get_headers()) - 1, { 'style': 'Table Style Medium 7', 'columns': table_headers, # The name of the Table should only containt letters + numbers. # 'name'c: s.info["name"].replace('[^[a-zA-Z0-9]', ''), 'autofilter': auto_filter_v, 'banded_rows': False, }) @@ -462,7 +470,8 @@ def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None) sheet.set_column(1, 1, 50) # Game name column size # Check if the collection has any games at all before exporting it logger.debug("Special collection %s has %s games", name, len(collection.games)) if len(collection.games) < 1: logger.info("Special collection %s has no games, sheet will be empty", name) continue @@ -583,4 +592,4 @@ def parse_arguments(): xlsx_export_workbook(systems, output, collections) logger.debug("Finished") -
cmitu revised this gist
Feb 25, 2018 . 1 changed file with 125 additions and 10 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,6 +3,7 @@ import xml.etree.ElementTree as et import logging as log import os.path import fnmatch import argparse import xlsxwriter @@ -193,7 +194,30 @@ def check_rom(rom_folder, rom_path): return os.path.isfile(path_to_check) def get_rom_path(rom_folder, rom_path): if not rom_path.startswith('/'): path_to_check = rom_folder + "/" + rom_path return os.path.realpath(path_to_check) def get_roms_in_collection(rom_path_list, all_games): """ Produce a list of Game objects, from @rom_path - a list of ROM paths @all_games - a list of all Game objects. """ roms = [] for rom in all_games: if rom.info['realpath'] in rom_path_list: logger.debug("Found game %s at path %s", rom.info['name'], rom.info['realpath']) roms.append(rom) return roms def skip_system(system_name): return str(system_name).upper() in map(lambda x: x.upper(), skipped_systems) @@ -246,6 +270,8 @@ def parse_systems(): # Check if the ROM/Game file is on disk. Add it to the list only of it exists. if check_rom(s.info['path'], rom.info['path']): s.games.append(rom) # Get the ROM's real path, to handle custom collections rom.info['realpath'] = get_rom_path(s.info['path'], rom.info['path']) else: logger.debug("ROM %s not found in %s, removed from export",rom.info['name'], s.info['path']) @@ -261,9 +287,49 @@ def parse_systems(): return systems def parse_custom_collections(): """ Tries to find the custom ES defined collections, which should be under $HOME/.emulationstation/collections Each collection is a file named 'custom-XYZ.cfg', which contains a list of ROM paths. Open each .cfg file and read the list of paths. Return a dict containing - the collection name - the corresponging list of ROM paths. """ collections = {} logger.debug("Trying to find custom collections") custom_collections_folder = "{0}/.emulationstation/collections".format(os.environ['HOME']) if not os.path.isdir(custom_collections_folder): logger.info("No custom collection folder found, skipping") return for file in os.listdir(custom_collections_folder): cfg_path = custom_collections_folder + '/' + file; if fnmatch.fnmatch(file, 'custom-*.cfg') and os.path.isfile(cfg_path): collection_name = file.replace('custom-', '').replace('.cfg', '').capitalize() logger.info("Found collection %s", collection_name) # OK, we have the file, open it and get it line by line try: cfg_file = open(cfg_path, "r") roms = cfg_file.readlines() logger.debug("Found %d roms in collection %s", len(roms), collection_name) # Add the collection in the dict, with the list of roms as value. # Since the realines() method above will return the name of ROM followed by a '\n' # run a map over the list of ROMs to remove any stray '\n' collections[collection_name] = list(map(lambda r: r.strip('\n'), roms)) except Exception: logger.warn("Cannot read collection file %s", file) return collections # Export the system list to excel def xlsx_export_workbook(systems, output='export.xlsx', custom_collections=None): if not len(systems): raise "Exported system list is empty" @@ -276,7 +342,8 @@ def xlsx_export_workbook(systems, output='export.xlsx'): all_collection = System.get_collection('all') fav_collection = System.get_collection('favorite') kid_collection = System.get_collection('kid') # Create the Workbook wb = xlsxwriter.Workbook(output, {'default_date_format': 'dd-mm-yyyy', @@ -316,7 +383,18 @@ def xlsx_export_workbook(systems, output='export.xlsx'): kid_sheet = wb.add_worksheet("Kid Games") kid_sheet.set_tab_color('pink') custom_sheets = {} if len(custom_collections)>0 : logger.debug("Adding custom collections to export") for collection in custom_collections: if len(custom_collections[collection]) > 0: logger.debug("Exporting custom collection %s", collection) s = wb.add_worksheet(collection) s.set_tab_color("gray") custom_sheets[collection] = s # The table headers for the each system's sheet table_headers = list(map(lambda x: {'header': str(x).capitalize()}, Game.get_headers())) @@ -372,7 +450,7 @@ def xlsx_export_workbook(systems, output='export.xlsx'): fmt_bold, sum(map(lambda system: len(system.games), systems))) # Write the special Collection (All, Kid Games, Favorites) special_collections = ( (all_sheet, all_collection, "All"), (fav_sheet, fav_collection, "Favorites"), @@ -382,12 +460,17 @@ def xlsx_export_workbook(systems, output='export.xlsx'): for (sheet, collection, name) in special_collections: sheet.set_column(0, 0, 20) # System column size sheet.set_column(1, 1, 50) # Game name column size # Check if the collection has any games at all before exporting it if len(collection.name) < 1: logger.info("Special collection %s has no games, sheet will be empty", name) continue t = sheet.add_table(0, 0, len(collection.games), len(Game.get_headers()), { 'style': 'Table Style Light 9', 'columns': [{'header': "System"}] + table_headers, # 'name': name }) for j, g in enumerate(collection.games): @@ -397,6 +480,36 @@ def xlsx_export_workbook(systems, output='export.xlsx'): sheet.set_column('C:C', None, None, {'hidden': True}) sheet.set_column('I:I', 12) sheet.set_column('J:J', 12) # Write the Custom Collections for c in custom_sheets: logger.debug("Writing custom collection %s", c) # Produce a list of Game objects based on the paths of ROMs rom_list = get_roms_in_collection(custom_collections[c], all_collection.games) logger.debug("Should write %d games to %s collection", len(rom_list), c) # Ok, write the info in the custom collection worksheet s = custom_sheets[c] logger.debug("Adding custom collection in sheet %s", s.get_name()) s.set_column(0, 0, 20) # System column size s.set_column(1, 1, 50) # Game name column size t = s.add_table(0, 0, len(rom_list), len(Game.get_headers()), { 'style': 'Table Style Light 9', 'columns': [{'header': "System"}] + table_headers, # 'name': c # TODO: check if the collection name is a valid table name }) for j, g in enumerate(rom_list): xlsx_export_system_row(wb, s, j+1, g, g.info["system"]) # hide the Path column and set the size for Release date and LastPlayed s.set_column('C:C', None, None, {'hidden': True}) s.set_column('I:I', 12) s.set_column('J:J', 12) # Close the workbook wb.close() @@ -460,12 +573,14 @@ def parse_arguments(): logger.debug("Starting") systems = parse_systems() collections = parse_custom_collections(); # See how many games we have total_games = sum(map(lambda system: len(system.games), systems)) logger.info("Total games after parsing gamelist files - " + str(total_games)) logger.info("Exporting to file %s",output) xlsx_export_workbook(systems, output, collections) logger.debug("Finished") -
cmitu revised this gist
Feb 19, 2018 . 1 changed file with 7 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,7 +12,7 @@ skipped_systems = ['retropie', 'kodi'] # Set up logging using the logging module. log.basicConfig(level=log.INFO, format=u"%(asctime)s %(levelname)-6s %(message)s") logger = log.getLogger(__name__) @@ -225,13 +225,13 @@ def parse_systems(): continue # Try to open and parse the gamelist for this system. logger.debug("Analyzing system: %s (%s)",s.info['fullname'], s.info['name']) try: gamelist_path = get_gamelist(s.info['name'], s.info['path']) if gamelist_path is None: logger.debug("%s system has no gamelist, skipping",s.info['fullname']) continue gamelist = et.parse(gamelist_path) @@ -247,19 +247,17 @@ def parse_systems(): if check_rom(s.info['path'], rom.info['path']): s.games.append(rom) else: logger.debug("ROM %s not found in %s, removed from export",rom.info['name'], s.info['path']) # Show how many games we have on the system logger.debug("Found %d game(s) for %s %s", len(s.games), s.info['fullname'], s.info['name']) # If we have more than 1 ROM in the system, add it to the exported list if len(s.games) > 0: systems.append(s) else: logger.debug( "System %s has no games/roms, it's excluded from the export", s.info['name']) return systems @@ -467,7 +465,7 @@ def parse_arguments(): total_games = sum(map(lambda system: len(system.games), systems)) logger.info("Total games after parsing gamelist files - " + str(total_games)) logger.info("Exporting to file %s",output) xlsx_export_workbook(systems, output) logger.debug("Finished") -
cmitu revised this gist
Feb 18, 2018 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -341,7 +341,7 @@ def xlsx_export_workbook(systems, output='export.xlsx'): 'style': 'Table Style Medium 7', 'columns': table_headers, # The name of the Table should only containt letters + numbers. # 'name'c: s.info["name"].replace('[^[a-zA-Z0-9]', ''), 'autofilter': True, 'banded_rows': False, }) @@ -433,7 +433,7 @@ def xlsx_export_system_row(workbook, sheet, row_number, game, system_name=None): sheet.write(row_number, column + offset, game.info[header]) # If we're on the 'All' sheet, add the description of the game in the cell comments if sheet.get_name().lower() == "all" and header.lower() == "name" and not game.info['desc'] is None: sheet.write_comment(row_number, column + offset, game.info['desc'], {'x_scale': 4, 'y_scale': 4}) @@ -470,4 +470,4 @@ def parse_arguments(): logger.info("Exporting to file {0}".format(output)) xlsx_export_workbook(systems, output) logger.debug("Finished") -
cmitu revised this gist
Feb 18, 2018 . 1 changed file with 8 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -61,9 +61,10 @@ def get_xml_element_date(xml, node_name): Returns a DateTime or a String, depending on the value of the @parm node_name. """ ES_TIME_FORMAT = "%Y%m%dT%H%M%S" if not xml.find(node_name) is None and not xml.find(node_name).text is None: date_text = xml.find(node_name).text # Release date can appear as both ISO date or just as an year. # If it's an ISO date, then try to convert it, otherwise just return the text if len(date_text) < len('19860101T000000'): @@ -90,6 +91,8 @@ def get_xml_element_int(xml, node_name): return int(xml.find(node_name).text) except ValueError: return xml.find(node_name).text except TypeError: return None class System(object): @@ -337,7 +340,8 @@ def xlsx_export_workbook(systems, output='export.xlsx'): { 'style': 'Table Style Medium 7', 'columns': table_headers, # The name of the Table should only containt letters + numbers. # 'name': s.info["name"].replace('[^[a-zA-Z0-9]', ''), 'autofilter': True, 'banded_rows': False, }) @@ -466,4 +470,4 @@ def parse_arguments(): logger.info("Exporting to file {0}".format(output)) xlsx_export_workbook(systems, output) logger.debug("Finished") -
cmitu revised this gist
Feb 17, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -337,7 +337,7 @@ def xlsx_export_workbook(systems, output='export.xlsx'): { 'style': 'Table Style Medium 7', 'columns': table_headers, # 'name': s.info["name"], 'autofilter': True, 'banded_rows': False, }) -
cmitu revised this gist
Feb 11, 2018 . No changes.There are no files selected for viewing
-
cmitu created this gist
Feb 10, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,469 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- import xml.etree.ElementTree as et import logging as log import os.path import argparse import xlsxwriter from datetime import datetime as dt # List of systems that are not to be exported. skipped_systems = ['retropie', 'kodi'] # Set up logging using the logging module. log.basicConfig(level=log.INFO, format="%(asctime)s %(levelname)-6s %(message)s") logger = log.getLogger(__name__) def get_xml_element_text(xml, node_name): if xml.find(node_name) is None: return "" else: return xml.find(node_name).text def is_number(s): try: int(s) return True except: return False def is_float(s): try: float(s) return True except: return False def get_xml_element_bool(xml, node_name): """ Returns either yes or None, depending on the value of the @parm node_name. """ if xml.find(node_name) is None: return None elif xml.find(node_name).text.lower() == "false" or xml.find(node_name).text.lower() == "no": return None else: return "yes" def get_xml_element_date(xml, node_name): """ Returns a DateTime or a String, depending on the value of the @parm node_name. """ ES_TIME_FORMAT = "%Y%m%dT%H%M%S" if not xml.find(node_name) is None: date_text = xml.find(node_name).text # Release date can appear as both ISO date or just as an year. # If it's an ISO date, then try to convert it, otherwise just return the text if len(date_text) < len('19860101T000000'): return date_text else: try: date = dt.strptime(xml.find(node_name).text, ES_TIME_FORMAT) return date except ValueError: return date_text else: return None def get_xml_element_int(xml, node_name): """ Returns None or a Number, depending on the value of the @parm. """ if xml.find(node_name) is None: return None else: try: return int(xml.find(node_name).text) except ValueError: return xml.find(node_name).text class System(object): """ Class that models an ES System, storing the attributes of the System and its list of Games """ info_keys = ("name", "fullname", "path", "platform", "extension") def __init__(self, xml): self.info = dict.fromkeys(System.info_keys) self.games = [] # List of games for key in System.info_keys: self.info[key] = get_xml_element_text(xml, key) def __str__(self): return str(self.info['fullname'] + " (" + self.info['platform'] + "), path: " + self.info['path'] + ", games: " + str(len(self.games))) @staticmethod def get_collection(collection_name): o = System.__new__(System) o.name = collection_name o.fullname = collection_name o.games = [] return o class Game: info_keys = ("name", "path", "publisher", "developer", "genre", "players", "rating") info_desc = ("desc") info_bool = ("favorite", "kidgame", "hidden") info_date = ("releasedate", "lastplayed") info_int = ("playcount",) @staticmethod def get_headers(): return (Game.info_keys + Game.info_date + Game.info_bool + Game.info_int) def __init__(): self.info = dict.fromkeys(Game.get_headers()) def __init__(self, obj): self.info = dict.fromkeys(Game.info_keys) # Get the text metadata for attr in self.info.keys(): self.info[attr] = get_xml_element_text(obj, attr) # Get the date metadata for attr in Game.info_date: self.info[attr] = get_xml_element_date(obj, attr) # Get the boolean metadata for attr in Game.info_bool: self.info[attr] = get_xml_element_bool(obj, attr) # Get the integer metadata for attr in Game.info_int: self.info[attr] = get_xml_element_int(obj, attr) # Get the description self.info["desc"] = get_xml_element_text(obj, "desc") def __str__(self): return str("{0}\t{1}".format(self.info["name"]), str(self.info["path"])) # The gamelist.xml can be found in # * ROM folder for the system # * $HOME/.emulationstation/gamelists/$name def get_gamelist(system, rom_folder): rom_folder_gamelist = rom_folder + "/gamelist.xml" es_folder_gamelist = "{0}/.emulationstation/gamelists/{1}/gamelist.xml".format( os.environ['HOME'], system) if os.path.isfile(rom_folder_gamelist): return rom_folder_gamelist elif os.path.isfile(es_folder_gamelist): return es_folder_gamelist else: return None def check_rom(rom_folder, rom_path): """ Method to check if a ROM is present in the filesystem. Returns true if the ROM is present, false otherwise. """ # The Rom path in the gamelist might be absolute or relative. # Check if the path begins with an '/' to decide if it's an absolute path. path_to_check = rom_path if not rom_path.startswith('/'): path_to_check = rom_folder + "/" + rom_path return os.path.isfile(path_to_check) def skip_system(system_name): return str(system_name).upper() in map(lambda x: x.upper(), skipped_systems) # Parsing the 'es_systems.cfg' file, from either $HOME/.emulationstation or /etc/emulationstaton def parse_systems(): es_system_file = '/etc/emulationstation/es_systems.cfg' systems = [] if os.path.isfile(os.environ['HOME'] + "/.emulationstation/es_systems.cfg"): es_system_file = os.environ['HOME'] + "/.emulationstation/es_systems.cfg" logger.info("Emulationstation systems file used: " + es_system_file) # Parse the Emulationstation systems file sys = et.parse(es_system_file) for system in sys.getroot().findall('system'): s = System(system) if s.info['path'] is None or s.info['name'] is None: logger.debug("System {0} has no path or name, skipping".format(s.info['fullname'])) continue if skip_system(s.info['name']): logger.info("System {0} is skipped as configured".format(s.info['fullname'])) continue # Try to open and parse the gamelist for this system. logger.debug("Analyzing system: {0} ({1})".format(s.info['fullname'], s.info['name'])) try: gamelist_path = get_gamelist(s.info['name'], s.info['path']) if gamelist_path is None: logger.debug("{0} system has no gamelist, skipping".format(s.info['fullname'])) continue gamelist = et.parse(gamelist_path) except IOError: logger.warn("Could not open the gamelist for " + s.info['name'] + ", skipping !") continue # Ok, we have the gamelist, get each game and parse it. for game in gamelist.getroot().findall('game'): rom = Game(game) # Check if the ROM/Game file is on disk. Add it to the list only of it exists. if check_rom(s.info['path'], rom.info['path']): s.games.append(rom) else: logger.debug("ROM {0} not found in {1}, removed from export".format( rom.info['name'], s.info['path'])) # Show how many games we have on the system logger.debug("Found {0} game(s) for {1} ({2})".format( len(s.games), s.info['fullname'], s.info['name'])) # If we have more than 1 ROM in the system, add it to the exported list if len(s.games) > 0: systems.append(s) else: logger.debug( "System {0} has no games/roms, it's excluded from the export".format(s.info['name'])) return systems # Export the system list to excel def xlsx_export_workbook(systems, output='export.xlsx'): if not len(systems): raise "Exported system list is empty" return # Special collections. Some of them might be empty # * All games # * Favorite games # * Kid games all_collection = System.get_collection('all') fav_collection = System.get_collection('favorite') kid_collection = System.get_collection('kid') # Create the Workbook wb = xlsxwriter.Workbook(output, {'default_date_format': 'dd-mm-yyyy', 'in_memory': True, }) # Add some metadata to it wb.set_properties({ 'title': 'Game List Export', 'subject': 'Emulationstation Games', 'category': 'Gaming', 'author': "XlsxWriter (github.com/jmcnamara/XlsxWriter), version " + xlsxwriter.__version__, 'comments': 'This is a complete list of games registered in Emulationstation.\nDocument produced on ' + dt.now().strftime("%c") + '\nSystems: ' + ', '.join(list(sorted(set(map(lambda system: system.info['fullname'], systems))))) }) wb.set_custom_property('Date Exported', dt.now()) fmt_bold = wb.add_format({'bold': True}) fmt_bold_2 = wb.add_format({'bold': True, 'bg_color': 'red', 'color': 'white'}) fmt_sys_header = wb.add_format({'bold': True, 'bg_color': 'green', 'color': 'white'}) fmt_fav_row = wb.add_format({'bg_color': '#FFCC7C'}) # Add a summary sheet as the 1st sheet in the workbook start = wb.add_worksheet("Summary") start.write_row(0, 0, ("System", "Total"), fmt_bold_2) start.set_tab_color('blue') start.set_column(0, 0, 50) # Add special collection sheets all_sheet = wb.add_worksheet("All") all_sheet.set_tab_color('green') fav_sheet = wb.add_worksheet("Favorites") fav_sheet.set_tab_color("yellow") kid_sheet = wb.add_worksheet("Kid Games") kid_sheet.set_tab_color('pink') # The table headers for the each system's sheet table_headers = list(map(lambda x: {'header': str(x).capitalize()}, Game.get_headers())) for i, s in enumerate(systems): # Add a worksheet for each system. b = wb.add_worksheet(s.info['name']) # Create a table with each system and the # of games detected in each system. # Make the system column be a link to the sheet with the system games. start.write_url(i+1, 0, "internal:'" + s.info['name'] + "'!A1", string="{0} ({1})".format(s.info['fullname'], s.info['name']) ) start.write(i+1, 1, len(s.games)) # Print the table header b.set_column(0, 0, 50) t = b.add_table(0, 0, len(s.games), len(Game.get_headers()) - 1, { 'style': 'Table Style Medium 7', 'columns': table_headers, 'name': s.info["name"], 'autofilter': True, 'banded_rows': False, }) # Print the table rows for j, g in enumerate(s.games): xlsx_export_system_row(wb, b, j+1, g) # Add the game to the 'All' collection g.info["system"] = s.info["name"] all_collection.games.append(g) # Check if the game goes into another special collection (favorites, kidgames) if g.info["favorite"]: fav_collection.games.append(g) if g.info["kidgame"]: kid_collection.games.append(g) # Hide the 'Path' column (2nd one) b.set_column('B:B', None, None, {'hidden': True}) # Set the size for the Release Date, Last played b.set_column('H:H', 12) b.set_column('I:I', 12) # Add a total row on the start sheet start.write(len(systems)+1, 0, "Total", fmt_bold) start.write_formula(len(systems)+1, 1, "=SUM(B1:B" + str(len(systems) + 1) + ")", fmt_bold, sum(map(lambda system: len(system.games), systems))) # Write the special Collection special_collections = ( (all_sheet, all_collection, "All"), (fav_sheet, fav_collection, "Favorites"), (kid_sheet, kid_collection, "KidGames") ) for (sheet, collection, name) in special_collections: sheet.set_column(0, 0, 20) # System column size sheet.set_column(1, 1, 50) # Game name column size t = sheet.add_table(0, 0, len(collection.games), len(Game.get_headers()), { 'style': 'Table Style Light 9', 'columns': [{'header': "System"}] + table_headers, 'name': name }) for j, g in enumerate(collection.games): xlsx_export_system_row(wb, sheet, j+1, g, g.info["system"]) # hide the Path column and set the size for Release date and LastPlayed sheet.set_column('C:C', None, None, {'hidden': True}) sheet.set_column('I:I', 12) sheet.set_column('J:J', 12) # Close the workbook wb.close() def xlsx_export_system_row(workbook, sheet, row_number, game, system_name=None): fmt_fav = workbook.add_format({'align': 'center'}) # On special collections, 1st column is the name of the system where the game belongs # Only shown when set. if system_name is not None: sheet.write(row_number, 0, system_name) offset = 1 else: offset = 0 for column, header in enumerate(Game.get_headers()): if header in Game.info_date and type(game.info[header]).__name__ == "datetime": sheet.write_datetime(row_number, column + offset, game.info[header]) elif header in ('playcount', 'players') and is_number(game.info[header]): sheet.write_number(row_number, column + offset, int(game.info[header])) elif header in ('rating',) and is_float(game.info[header]): sheet.write_number(row_number, column + offset, float(game.info[header])) elif header.lower() in ('favorite', 'kidgame', 'hidden'): sheet.write(row_number, column + offset, game.info[header], fmt_fav) else: sheet.write(row_number, column + offset, game.info[header]) # If we're on the 'All' sheet, add the description of the game in the cell comments if sheet.get_name().lower() == "all" and header.lower() == "name": sheet.write_comment(row_number, column + offset, game.info['desc'], {'x_scale': 4, 'y_scale': 4}) def parse_arguments(): parser = argparse.ArgumentParser( description='Export Emulationstation gamelist files to an Excel file') parser.add_argument('output', nargs='?', default="export_" + dt.now().strftime("%d-%m-%Y") + ".xlsx", help="Export file (default is 'export_" + dt.now().strftime("%d-%m-%Y") + ".xlsx')") parser.add_argument('-d', '--debug', action='store_true', help="run script with with debug info", default=False) args = parser.parse_args() return (args.output, args.debug) if __name__ == "__main__": # Parse arguments (output, debug) = parse_arguments() # Set logging level; default is INFO, add debugging if requested via parameter if debug: logger.setLevel(log.DEBUG) logger.debug("Starting") systems = parse_systems() # See how many games we have total_games = sum(map(lambda system: len(system.games), systems)) logger.info("Total games after parsing gamelist files - " + str(total_games)) logger.info("Exporting to file {0}".format(output)) xlsx_export_workbook(systems, output) logger.debug("Finished")