class MainWin(wx.Frame): def __init__(self, parent, id=wx.ID_ANY, title='', size=(200, 200)): wx.Frame.__init__(self, parent, id, title, size=size) self.SetBackgroundColour(wx.Colour(240, 240, 240)) self.fname = None self.updated = False self.firstTime = True self.lastUpdateTime = None self.comments = [] self.filehistory = wx.FileHistory(16) self.config = wx.Config(appName="StageRaceGC", vendorName="*****@*****.**", style=wx.CONFIG_USE_LOCAL_FILE) self.filehistory.Load(self.config) inputBox = wx.StaticBox(self, label=_('Input')) inputBoxSizer = wx.StaticBoxSizer(inputBox, wx.VERTICAL) self.fileBrowse = filebrowse.FileBrowseButtonWithHistory( self, labelText=_('Excel File'), buttonText=('Browse...'), startDirectory=os.path.expanduser('~'), fileMask= 'Excel Spreadsheet (*.xlsx; *.xlsm; *.xls)|*.xlsx; *.xlsml; *.xls', size=(400, -1), history=lambda: [ self.filehistory.GetHistoryFile(i) for i in xrange(self.filehistory.GetCount()) ], changeCallback=self.doChangeCallback, ) inputBoxSizer.Add(self.fileBrowse, 0, flag=wx.EXPAND | wx.ALL, border=4) horizontalControlSizer = wx.BoxSizer(wx.HORIZONTAL) self.updateButton = RoundButton(self, size=(96, 96)) self.updateButton.SetLabel(_('Update')) self.updateButton.SetFontToFitLabel() self.updateButton.SetForegroundColour(wx.Colour(0, 100, 0)) self.updateButton.Bind(wx.EVT_BUTTON, self.doUpdate) horizontalControlSizer.Add(self.updateButton, flag=wx.ALL, border=4) horizontalControlSizer.AddSpacer(48) vs = wx.BoxSizer(wx.VERTICAL) self.tutorialButton = wx.Button(self, label=_('Help/Tutorial...')) self.tutorialButton.Bind(wx.EVT_BUTTON, self.onTutorial) vs.Add(self.tutorialButton, flag=wx.ALL, border=4) branding = wx.adv.HyperlinkCtrl( self, id=wx.ID_ANY, label=u"Powered by CrossMgr", url=u"http://www.sites.google.com/site/crossmgrsoftware/") vs.Add(branding, flag=wx.ALL, border=4) horizontalControlSizer.Add(vs) self.openExcel = wx.Button(self, label=_('Open Excel File...')) self.openExcel.Bind(wx.EVT_BUTTON, self.onOpenExcel) horizontalControlSizer.AddSpacer(48) horizontalControlSizer.Add(self.openExcel, flag=wx.ALIGN_RIGHT | wx.ALL, border=4) inputBoxSizer.Add(horizontalControlSizer, flag=wx.EXPAND) self.stageList = ListMixCtrl(self, style=wx.LC_REPORT, size=(-1, 160)) self.stageList.InsertColumn(0, "Sheet") self.stageList.InsertColumn(1, "Bibs", wx.LIST_FORMAT_RIGHT) self.stageList.InsertColumn(2, "Errors/Warnings") self.stageList.setResizeColumn(2) bookStyle = (flatnotebook.FNB_NO_X_BUTTON | flatnotebook.FNB_FF2 | flatnotebook.FNB_NODRAG | flatnotebook.FNB_DROPDOWN_TABS_LIST | flatnotebook.FNB_NO_NAV_BUTTONS | flatnotebook.FNB_BOTTOM) self.notebook = flatnotebook.FlatNotebook(self, 1000, agwStyle=bookStyle) self.notebook.SetBackgroundColour(wx.WHITE) self.saveAsExcelButton = wx.Button(self, label=u'Save as Excel') self.saveAsExcelButton.Bind(wx.EVT_BUTTON, self.saveAsExcel) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(inputBoxSizer, flag=wx.EXPAND | wx.ALL, border=4) mainSizer.Add(self.stageList, flag=wx.EXPAND | wx.ALL, border=4) mainSizer.Add(self.notebook, 1, flag=wx.EXPAND | wx.ALL, border=4) mainSizer.Add(self.saveAsExcelButton, flag=wx.ALL, border=4) self.SetSizer(mainSizer) def onOpenExcel(self, event): filename = self.fileBrowse.GetValue() if not filename: return wait = wx.BusyCursor() Utils.LaunchApplication(filename) def onTutorial(self, event): if not Utils.MessageOKCancel( self, u"\n".join([ _("Launch the StageRaceGC Tutorial."), _("This open a sample Excel input file created into your home folder." ), _("This data in this sheet is made-up, although it does include some current rider's names." ), u"", _("It will also open the Tutorial page in your browser. If you can't see your browser, make sure you bring to the front." ), u"", _("Continue?"), ])): return try: fname_excel = MakeExampleExcel() except Exception as e: traceback.print_exc() Utils.MessageOK( self, u'{}\n\n{}\n\n{}'.format( u'Problem creating Excel sheet.', e, _('If the Excel file is open, please close it and try again' ))) return self.fileBrowse.SetValue(fname_excel) self.doUpdate(event) Utils.LaunchApplication(fname_excel) Utils.LaunchApplication( os.path.join(Utils.getHtmlDocFolder(), 'Tutorial.html')) def doChangeCallback(self, event): fname = event.GetString() if not fname: self.setUpdated(False) return if fname != self.fname: wx.CallAfter(self.doUpdate, fnameNew=fname) def setUpdated(self, updated=True): self.updated = updated for w in [self.stageList, self.saveAsExcelButton]: w.Enable(updated) if not updated: self.stageList.DeleteAllItems() self.notebook.DeleteAllPages() def updateStageList(self, registration=None, stages=None): self.stageList.DeleteAllItems() registration = (registration or (Model.model and Model.model.registration) or None) if not registration: return stages = (stages or (Model.model and Model.model.stages) or []) def insert_stage_info(stage): idx = self.stageList.InsertItem(sys.maxint, stage.sheet_name) self.stageList.SetItem(idx, 1, unicode(len(stage))) if stage.errors: self.stageList.SetItem( idx, 2, u'{}: {}'.format( len(stage.errors), u' '.join(u'[{}]'.format(e) for e in stage.errors))) else: self.stageList.SetItem( idx, 2, u' ' ) insert_stage_info(registration) for stage in stages: insert_stage_info(stage) for col in xrange(3): self.stageList.SetColumnWidth(col, wx.LIST_AUTOSIZE) self.stageList.SetColumnWidth(1, 52) self.stageList.Refresh() def callbackUpdate(self, message): pass def doUpdate(self, event=None, fnameNew=None): try: self.fname = (fnameNew or event.GetString() or self.fileBrowse.GetValue()) except: self.fname = u'' if not self.fname: Utils.MessageOK( self, _('Missing Excel file. Please select an Excel file.'), _('Missing Excel File')) self.setUpdated(False) return if self.lastUpdateTime and (datetime.datetime.now() - self.lastUpdateTime).total_seconds() < 1.0: return try: with open(self.fname, 'rb') as f: pass except Exception as e: traceback.print_exc() Utils.MessageOK( self, u'{}:\n\n {}\n\n{}'.format(_('Cannot Open Excel file'), self.fname, e), _('Cannot Open Excel File')) self.setUpdated(False) return self.filehistory.AddFileToHistory(self.fname) self.filehistory.Save(self.config) self.fileBrowse.SetValue(self.fname) wait = wx.BusyCursor() labelSave, backgroundColourSave = self.updateButton.GetLabel( ), self.updateButton.GetForegroundColour() try: Model.read(self.fname, callbackfunc=self.updateStageList) except Exception as e: traceback.print_exc() Utils.MessageOK( self, u'{}:\n\n {}\n\n{}'.format(_('Excel File Error'), self.fname, e), _('Excel File Error')) self.setUpdated(False) return Model.model.getGCs() self.setUpdated(True) self.updateStageList() StageRaceGCToGrid(self.notebook) self.lastUpdateTime = datetime.datetime.now() def getOutputExcelName(self): fname_base, fname_suffix = os.path.splitext(self.fname) fname_excel = '{}-{}{}'.format(fname_base, 'GC', '.xlsx') return fname_excel def saveAsExcel(self, event): fname_excel = self.getOutputExcelName() if os.path.isfile(fname_excel): if not Utils.MessageOKCancel( self, u'"{}"\n\n{}'.format(fname_excel, _('File exists. Replace?')), _('Output Excel File Exists'), ): return try: StageRaceGCToExcel(fname_excel, Model.model) except Exception as e: Utils.MessageOK( self, u'{}: "{}"\n\n{}\n\n"{}"'.format( _("Write Failed"), e, _("If you have this file open, close it and try again."), fname_excel), _("Excel Write Failed."), iconMask=wx.ICON_ERROR, ) return wait = wx.BusyCursor() Utils.LaunchApplication(fname_excel)
class MainWin(wx.Frame): def __init__(self, parent, id=wx.ID_ANY, title='', size=(200, 200)): wx.Frame.__init__(self, parent, id, title, size=size) self.SetBackgroundColour(wx.Colour(240, 240, 240)) self.fname = None self.updated = False self.firstTime = True self.lastUpdateTime = None self.sources = [] self.errors = [] self.filehistory = wx.FileHistory(16) dataDir = Utils.getHomeDir() configFileName = os.path.join(dataDir, 'CallupSeedingMgr.cfg') self.config = wx.Config(appName="CallupSeedingMgr", vendorName="SmartCyclingSolutions", localFilename=configFileName) self.filehistory.Load(self.config) ID_MENU_UPDATE = wx.NewIdRef() ID_MENU_HELP = wx.NewIdRef() self.menuBar = wx.MenuBar(wx.MB_DOCKABLE) if 'WXMAC' in wx.Platform: self.appleMenu = self.menuBar.OSXGetAppleMenu() self.appleMenu.SetTitle("CallupSeedingMgr") self.appleMenu.Insert(0, wx.ID_ABOUT, "&About") self.Bind(wx.EVT_MENU, self.OnAboutBox, id=wx.ID_ABOUT) self.editMenu = wx.Menu() self.editMenu.Append( wx.MenuItem(self.editMenu, ID_MENU_UPDATE, "&Update")) self.Bind(wx.EVT_MENU, self.doUpdate, id=ID_MENU_UPDATE) self.menuBar.Append(self.editMenu, "&Edit") self.helpMenu = wx.Menu() self.helpMenu.Append( wx.MenuItem(self.helpMenu, ID_MENU_HELP, "&Help")) self.menuBar.Append(self.helpMenu, "&Help") self.Bind(wx.EVT_MENU, self.onTutorial, id=ID_MENU_HELP) else: self.fileMenu = wx.Menu() self.fileMenu.Append( wx.MenuItem(self.fileMenu, ID_MENU_UPDATE, "&Update")) self.fileMenu.Append(wx.ID_EXIT) self.Bind(wx.EVT_MENU, self.doUpdate, id=ID_MENU_UPDATE) self.Bind(wx.EVT_MENU, self.onClose, id=wx.ID_EXIT) self.menuBar.Append(self.fileMenu, "&File") self.helpMenu = wx.Menu() self.helpMenu.Insert(0, wx.ID_ABOUT, "&About") self.helpMenu.Insert(1, ID_MENU_HELP, "&Help") self.Bind(wx.EVT_MENU, self.OnAboutBox, id=wx.ID_ABOUT) self.Bind(wx.EVT_MENU, self.onTutorial, id=ID_MENU_HELP) self.menuBar.Append(self.helpMenu, "&Help") self.SetMenuBar(self.menuBar) inputBox = wx.StaticBox(self, label=_('Input')) inputBoxSizer = wx.StaticBoxSizer(inputBox, wx.VERTICAL) self.fileBrowse = filebrowse.FileBrowseButtonWithHistory( self, labelText=_('Excel File'), buttonText=('Browse...'), startDirectory=os.path.expanduser('~'), fileMask= 'Excel Spreadsheet (*.xlsx; *.xlsm; *.xls)|*.xlsx; *.xlsml; *.xls', size=(400, -1), history=lambda: [ self.filehistory.GetHistoryFile(i) for i in range(self.filehistory.GetCount()) ], changeCallback=self.doChangeCallback, ) inputBoxSizer.Add(self.fileBrowse, 0, flag=wx.EXPAND | wx.ALL, border=4) horizontalControlSizer = wx.BoxSizer(wx.HORIZONTAL) #------------------------------------------------------------------------------------------- verticalControlSizer = wx.BoxSizer(wx.VERTICAL) self.useUciIdCB = wx.CheckBox(self, label=_("Use UCI ID (assume no errors)")) self.useUciIdCB.SetValue(True) verticalControlSizer.Add(self.useUciIdCB, flag=wx.ALL, border=4) self.useLicenseCB = wx.CheckBox( self, label=_("Use License (assume no errors)")) self.useLicenseCB.SetValue(True) verticalControlSizer.Add(self.useLicenseCB, flag=wx.ALL, border=4) self.soundalikeCB = wx.CheckBox( self, label=_("Match misspelled names with Sound-Alike")) self.soundalikeCB.SetValue(True) verticalControlSizer.Add(self.soundalikeCB, flag=wx.ALL, border=4) self.callupSeedingRB = wx.RadioBox( self, style=wx.RA_SPECIFY_COLS, majorDimension=1, label=_("Sequence"), choices=[ _("Callups: Highest ranked FIRST (Cyclo-cross, MTB)"), _("Seeding: Highest ranked LAST (Time Trials)"), ], ) verticalControlSizer.Add(self.callupSeedingRB, flag=wx.EXPAND | wx.ALL, border=4) verticalControlSizer.Add(wx.StaticText( self, label=_('Riders with no criteria will be sequenced randomly.')), flag=wx.ALL, border=4) horizontalControlSizer.Add(verticalControlSizer, flag=wx.EXPAND) self.updateButton = RoundButton(self, size=(96, 96)) self.updateButton.SetLabel(_('Update')) self.updateButton.SetFontToFitLabel() self.updateButton.SetForegroundColour(wx.Colour(0, 100, 0)) self.updateButton.Bind(wx.EVT_BUTTON, self.doUpdate) horizontalControlSizer.Add(self.updateButton, flag=wx.ALL, border=4) horizontalControlSizer.AddSpacer(48) vs = wx.BoxSizer(wx.VERTICAL) self.tutorialButton = wx.Button(self, label=_('Help/Tutorial...')) self.tutorialButton.Bind(wx.EVT_BUTTON, self.onTutorial) vs.Add(self.tutorialButton, flag=wx.ALL, border=4) branding = wx.adv.HyperlinkCtrl( self, id=wx.ID_ANY, label=u"Powered by CrossMgr", url=u"http://www.sites.google.com/site/crossmgrsoftware/") vs.Add(branding, flag=wx.ALL, border=4) horizontalControlSizer.Add(vs) inputBoxSizer.Add(horizontalControlSizer, flag=wx.EXPAND) self.sourceList = wx.ListCtrl(self, style=wx.LC_REPORT, size=(-1, 100)) inputBoxSizer.Add(self.sourceList, flag=wx.ALL | wx.EXPAND, border=4) self.sourceList.InsertColumn(0, "Sheet") self.sourceList.InsertColumn(1, "Data Columns and Derived Information") self.sourceList.InsertColumn(2, "Key Fields") self.sourceList.InsertColumn(3, "Rows", wx.LIST_FORMAT_RIGHT) self.sourceList.InsertColumn(4, "Errors/Warnings", wx.LIST_FORMAT_RIGHT) self.sourceList.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onItemSelected) instructions = [ _('Drag-and-Drop the row numbers on the Left to change the sequence.' ), _('Click on Points or Position cells for details.'), _('Orange Cells: Multiple Matches. Click on the cell to see what you need to fix in the spreadsheet.' ), _('Yellow Cells: Soundalike Matches. Click on the cell to validate if the names are matched correctly.' ), ] self.grid = ReorderableGrid(self) self.grid.CreateGrid(0, 1) self.grid.SetColLabelValue(0, u'') self.grid.EnableDragRowSize(False) self.grid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.onGridCellClick) #self.grid.Bind( wx.EVT_MOTION, self.onMouseOver ) outputBox = wx.StaticBox(self, label=_('Output')) outputBoxSizer = wx.StaticBoxSizer(outputBox, wx.VERTICAL) hs = wx.BoxSizer(wx.HORIZONTAL) self.excludeUnrankedCB = wx.CheckBox( self, label=_("Exclude riders with no ranking info")) hs.Add(self.excludeUnrankedCB, flag=wx.ALL | wx.ALIGN_CENTRE_VERTICAL, border=4) hs.AddSpacer(24) hs.Add(wx.StaticText(self, label=_("Output:")), flag=wx.ALL | wx.ALIGN_CENTRE_VERTICAL, border=4) self.topRiders = wx.Choice(self, choices=[ _('All Riders'), _('Top 5'), _('Top 10'), _('Top 15'), _('Top 20'), _('Top 25') ]) self.topRiders.SetSelection(0) hs.Add(self.topRiders, flag=wx.ALIGN_CENTRE_VERTICAL) self.saveAsExcel = wx.Button(self, label=_('Save as Excel...')) self.saveAsExcel.Bind(wx.EVT_BUTTON, self.doSaveAsExcel) hs.AddSpacer(48) hs.Add(self.saveAsExcel, flag=wx.ALL, border=4) outputBoxSizer.Add(hs) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(inputBoxSizer, flag=wx.EXPAND | wx.ALL, border=4) for i, instruction in enumerate(instructions): flag = wx.LEFT | wx.RIGHT if i == len(instructions) - 1: flag |= wx.BOTTOM mainSizer.Add(wx.StaticText(self, label=instruction), flag=flag, border=8) mainSizer.Add(self.grid, 1, flag=wx.EXPAND | wx.ALL, border=4) mainSizer.Add(outputBoxSizer, flag=wx.EXPAND | wx.ALL, border=4) self.SetSizer(mainSizer) def onClose(self, event): wx.Exit() def OnAboutBox(self, e): description = """CallupSeedingMgr is an Seeding Manager for CrossMgr """ licence = """CallupSeedingMgr free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. CallupSeedingMgr is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with File Hunter; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA""" info = wx.adv.AboutDialogInfo() crossMgrPng = Utils.getImageFolder() + '/CallupSeedingMgr.png' info.SetIcon(wx.Icon(crossMgrPng, wx.BITMAP_TYPE_PNG)) info.SetName('CallupSeedingMgr') info.SetVersion(AppVerName.split(' ')[1]) info.SetDescription(description) info.SetCopyright('(C) 2020 Edward Sitarski') info.SetWebSite('http://www.sites.google.com/site/crossmgrsoftware/') info.SetLicence(licence) wx.adv.AboutBox(info, self) def onTutorial(self, event): if not Utils.MessageOKCancel( self, u"\n".join([ _("Launch the CallupSeedingMgr Tutorial."), _("This open a sample Excel input file created into your home folder." ), _("This data in this sheet is made-up, although it does include some current rider's names." ), u"", _("It will also open the Tutorial page in your browser. If you can't see your browser, make sure you bring to the front." ), u"", _("Continue?"), ])): return try: fname_excel = MakeExampleExcel() self.fileBrowse.SetValue(fname_excel) except Exception as e: Utils.MessageOK( self, u'{}\n\n{}\n\n{}'.format( u'Problem creating Excel sheet.', e, _('If the Excel file is open, please close it and try again' ))) self.doUpdate(event) Utils.LaunchApplication([ fname_excel, os.path.join(Utils.getHtmlDocFolder(), 'Tutorial.html') ]) def onItemSelected(self, event): currentItem = event.GetIndex() errors = self.errors[(currentItem + len(self.errors) - 1) % len(self.errors)] if not errors: return dialog = ErrorDialog(self, errors=errors) dialog.ShowModal() dialog.Destroy() event.Skip() def onMouseOver(self, event): ''' Method to calculate where the mouse is pointing and then set the tooltip dynamically. ''' # Use CalcUnscrolledPosition() to get the mouse position # within the # entire grid including what's offscreen x, y = self.grid_area.CalcUnscrolledPosition(event.GetX(), event.GetY()) coords = self.grid_area.XYToCell(x, y) # you only need these if you need the value in the cell row = coords[0] col = coords[1] iRecord = int( self.grid.GetCellValue(row, self.grid.GetNumberCols() - 1)) iSource = self.grid.GetNumberCols() - col try: v = self.callup_results[iRecord][-iSource + 1] except IndexError: event.Skip() return try: status = v.get_status() except AttributeError: event.Skip() return if status == v.NoMatch: event.Skip() return message = u'{}\n\n{}'.format( v.get_message(), _('Make changes in the Spreadsheet (if necessary), then press "Update" to refresh the screen.' ), ) event.GetEventObject().SetToolTipString(message) event.Skip() def onGridCellClick(self, event): row = event.GetRow() col = event.GetCol() iRecord = int( self.grid.GetCellValue(row, self.grid.GetNumberCols() - 1)) iSource = self.grid.GetNumberCols() - col try: v = self.callup_results[iRecord][-iSource + 1] except IndexError: return try: status = v.get_status() except AttributeError: return if status == v.NoMatch: return message = u'{}\n\n{}'.format( v.get_message(), _('Make changes in the Spreadsheet (if necessary), then press "Update" to refresh the screen.' ), ) Utils.MessageOK( self, message, _('Soundalike Match') if status == v.SuccessSoundalike else _('Multiple Matches') if status == v.MultiMatch else _('Match Success')) def getTopRiders(self): i = self.topRiders.GetSelection() return 5 * i if i > 0 else 999999 def getIsCallup(self): return self.callupSeedingRB.GetSelection() == 0 def getIsSoundalike(self): return self.soundalikeCB.GetValue() def getUseUciId(self): return self.useUciIdCB.GetValue() def getUseLicense(self): return self.useLicenseCB.GetValue() def getOutputExcelName(self): fname = os.path.abspath(self.fname) dirname, basename = os.path.dirname(fname), os.path.basename(fname) fname_base, fname_suffix = os.path.splitext(basename) dirchild = 'CallupsOutput' if self.getIsCallup() else 'SeedingOutput' try: os.makedirs(os.path.join(dirname, dirchild)) except Exception as e: pass fname_excel = os.path.join( dirname, dirchild, '{}{}{}'.format(fname_base, '_Callups' if self.getIsCallup() else '_Seeding', '.xlsx')) return fname_excel def doChangeCallback(self, event): fname = event.GetString() if not fname: self.setUpdated(False) return if fname != self.fname: wx.CallAfter(self.doUpdate, fnameNew=fname) def setUpdated(self, updated=True): self.updated = updated for w in [self.sourceList, self.grid, self.saveAsExcel]: w.Enable(updated) if not updated: self.sourceList.DeleteAllItems() Utils.DeleteAllGridRows(self.grid) def updateSourceList(self, sources=None, errors=None): self.sourceList.DeleteAllItems() sources = (sources or self.sources) errors = (errors or self.errors) if not sources: return def insert_source_info(source, errors, add_value_field=True): idx = self.sourceList.InsertItem(999999, source.sheet_name) fields = source.get_ordered_fields() if add_value_field and source.get_cmp_policy_field(): fields = [source.get_cmp_policy_field()] + list(fields) self.sourceList.SetItem(idx, 1, u', '.join(make_title(f) for f in fields)) match_fields = source.get_match_fields( sources[-1]) if source != sources[-1] else [] self.sourceList.SetItem( idx, 2, u', '.join(make_title(f) for f in match_fields)) self.sourceList.SetItem(idx, 3, u'{}'.format(len(source.results))) self.sourceList.SetItem(idx, 4, u'{}'.format(len(errors))) insert_source_info(sources[-1], errors[-1], False) for i, source in enumerate(sources[:-1]): insert_source_info(source, errors[i]) for col in range(3): self.sourceList.SetColumnWidth(col, wx.LIST_AUTOSIZE) self.sourceList.SetColumnWidth(3, 52) self.sourceList.Refresh() def callbackUpdate(self, message): pass def doUpdate(self, event=None, fnameNew=None): try: self.fname = (fnameNew or event.GetString() or self.fileBrowse.GetValue()) except: self.fname = u'' if not self.fname: Utils.MessageOK( self, _('Missing Excel file. Please select an Excel file.'), _('Missing Excel File')) self.setUpdated(False) return if self.lastUpdateTime and (datetime.datetime.now() - self.lastUpdateTime).total_seconds() < 1.0: return try: with open(self.fname, 'rb') as f: pass except Exception as e: Utils.MessageOK( self, u'{}:\n\n {}\n\n{}'.format(_('Cannot Open Excel file'), self.fname, e), _('Cannot Open Excel File')) self.setUpdated(False) return self.filehistory.AddFileToHistory(self.fname) self.filehistory.Save(self.config) wait = wx.BusyCursor() labelSave, backgroundColourSave = self.updateButton.GetLabel( ), self.updateButton.GetForegroundColour() try: self.registration_headers, self.callup_headers, self.callup_results, self.sources, self.errors = GetCallups( self.fname, soundalike=self.getIsSoundalike(), useUciId=self.getUseUciId(), useLicense=self.getUseLicense(), callbackfunc=self.updateSourceList, callbackupdate=self.callbackUpdate, ) except Exception as e: traceback.print_exc() Utils.MessageOK( self, u'{}:\n\n {}\n\n{}'.format(_('Excel File Error'), self.fname, e), _('Excel File Error')) self.setUpdated(False) return self.setUpdated(True) self.updateSourceList() CallupResultsToGrid( self.grid, self.registration_headers, self.callup_headers, self.callup_results, is_callup=(self.callupSeedingRB.GetSelection() == 0), top_riders=self.getTopRiders(), exclude_unranked=self.excludeUnrankedCB.GetValue(), ) self.GetSizer().Layout() self.lastUpdateTime = datetime.datetime.now() def doSaveAsExcel(self, event): if self.grid.GetNumberRows() == 0: return fname_excel = self.getOutputExcelName() if os.path.isfile(fname_excel): if not Utils.MessageOKCancel( self, u'"{}"\n\n{}'.format(fname_excel, _('File exists. Replace?')), _('Output Excel File Exists'), ): return user_sequence = [ int(self.grid.GetCellValue(row, self.grid.GetNumberCols() - 1)) for row in range(self.grid.GetNumberRows()) ] user_callup_results = [self.callup_results[i] for i in user_sequence] try: CallupResultsToExcel( fname_excel, self.registration_headers, self.callup_headers, user_callup_results, is_callup=self.getIsCallup(), top_riders=self.getTopRiders(), exclude_unranked=self.excludeUnrankedCB.GetValue(), ) except Exception as e: traceback.print_exc() Utils.MessageOK( self, u'{}: "{}"\n\n{}\n\n"{}"'.format( _("Write Failed"), e, _("If you have this file open, close it and try again."), fname_excel), _("Excel Write Failed."), iconMask=wx.ICON_ERROR, ) return webbrowser.open(fname_excel, new=2, autoraise=True)