excel как найти расширение файла по умолчанию

Я пытаюсь написать приложение, которое создает файлы excel с использованием python и pywin32, и я хотел бы сохранить файл, используя формат и расширение по умолчанию для любой версии excel, которую использует пользователь. В зависимости от используемой версии Excel формат по умолчанию может быть «Open XML Workbook», в котором используется расширение «.xlsx». В других случаях это может быть базовый формат Excel и расширение «.xls». Кроме того, пользователь может настроить Excel на использование другого формата по умолчанию.

Я знаю, как найти формат по умолчанию (Application.DefaultSaveFormat), но не могу понять, как определить расширение по умолчанию для этого формата. Частично проблема заключается в том, что мои имена файлов имеют тенденцию включать точки даже перед расширением:
основное имя файла — «имя_файла.BOM», поэтому фактическое имя файла должно быть «имя_файла.BOM.xls» или «имя_файла.BOM». .xlsx" в зависимости от формата по умолчанию.

Если бы у меня не было двойной точки в имени файла, все было бы в порядке. Таким образом, если формат по умолчанию — «Рабочая книга Open XML», Workbook.SaveAs («имя файла») создаст файл с именем «имя файла.xlsx». Но Workbook.SaveAs("filename.BOM") создает файл с именем точно "filename.BOM". Excel не добавляет расширение по умолчанию, когда видит точку уже в имени файла.

Единственное, что я могу понять, это сохранить временный файл, получить от него расширение, а затем удалить временный файл, но это кажется действительно неуклюжим. У кого-нибудь есть лучшее решение?

from tempfile import mktemp
from os import path
from os import remove as delfile
class excel:
    def __init__( self):
        self.app = DispatchEx( "Excel.Application" )
    def saveas_default_ext_format( self, workbook, filename):
        # filename - file name with path but without extension

        tmpname = mktemp()

        alerts = self.app.DisplayAlerts
        self.app.DisplayAlerts = False
        workbook.SaveAs( tmpname)
        self.app.DisplayAlerts = alerts

        tmpname = self.app.ActiveWorkbook.FullName
        x, ext = path.splitext( tmpname)
        fullname = filename + ext
        workbook.SaveAs( fullname)

        delfile( tmpname)

        return fullname

person GarybCoder    schedule 15.11.2012    source источник
comment
Используйте .xls, все версии Excel будут учитывать его.   -  person Burhan Khalid    schedule 16.11.2012
comment
Вместо того, чтобы удалять временный файл и сохранять его снова под другим именем, почему бы просто не переименовать его?   -  person l4mpi    schedule 16.11.2012
comment
Вместо того, чтобы удалять временный файл, почему бы просто не переименовать его? - потому что вы не можете переименовать или удалить файл, пока он открыт в Excel, поскольку Excel блокирует файл.   -  person GarybCoder    schedule 16.11.2012


Ответы (2)


Почему бы не сделать список xlfileformats:extensions и использовать его для поиска:

from tempfile import mktemp
from os import path
from os import remove as delfile
class excel:
    def __init__( self):
        self.app = DispatchEx( "Excel.Application" )
        self.dct =     {51:'xlsx',
                        52:'xlsm',
                        50:'xlsb',
                        56:'xls'
                        }

    def saveas_default_ext_format( self, workbook, filename):
        # filename - file name with path but without extension


        fullname = '.'.join((filename, self.dct[self.app.DefaultSaveFormat]))
        workbook.SaveAs( fullname)

        return fullname

Я включил только наиболее распространенные форматы в образец словаря, но вы можете конкретизировать его из ряда источников в Интернете, например здесь. Я не добавлял обработчик исключений KeyError, но он вам, вероятно, понадобится.

удачи, Майк

person MikeHunter    schedule 15.11.2012
comment
Я искал более прямой способ поиска расширения. Однако я думаю, что это чище, чем сохранение временного файла. P.S. Предоставленная вами ссылка показывает перечисление каждого формата, но не дает расширения. Я искал, и таблицу, которая показывает оба, немного сложно найти, что странно. Я разберусь с этим. Спасибо Майк - person GarybCoder; 16.11.2012
comment
Да, вы должны определить расширение из константы xlFileFormat, список трудно найти. Но как только вы построите свой дикт, тогда он у вас есть. - person MikeHunter; 16.11.2012

Поскольку список, содержащий перечисления, значения и расширения в одном месте, трудно найти, вот как я это сделал. Сложная часть — заставить работать перечисления (см. код)

import win32com
from os.path import splitext

XlFileFormats = [ 
    'xlAddIn'                      , # Microsoft Excel 97-2003 Add-In
    'xlAddIn8'                     , # Microsoft Excel 97-2003 Add-In
    'xlCSV'                        , # CSV
    'xlCSVMac'                     , # Macintosh CSV
    'xlCSVMSDOS'                   , # MSDOS CSV
    'xlCSVWindows'                 , # Windows CSV
    'xlCurrentPlatformText'        , # Current Platform Text
    'xlDBF2'                       , # DBF2
    'xlDBF3'                       , # DBF3
    'xlDBF4'                       , # DBF4
    'xlDIF'                        , # DIF
    'xlExcel12'                    , # Excel12
    'xlExcel2'                     , # Excel2
    'xlExcel2FarEast'              , # Excel2 FarEast
    'xlExcel3'                     , # Excel3
    'xlExcel4'                     , # Excel4
    'xlExcel4Workbook'             , # Excel4 Workbook
    'xlExcel5'                     , # Excel5
    'xlExcel7'                     , # Excel7
    'xlExcel8'                     , # Excel8
    'xlExcel9795'                  , # Excel9795
    'xlHtml'                       , # HTML format
    'xlIntlAddIn'                  , # International Add-In
    'xlIntlMacro'                  , # International Macro
    'xlOpenDocumentSpreadsheet'    , # OpenDocument Spreadsheet
    'xlOpenXMLAddIn'               , # Open XML Add-In
    'xlOpenXMLTemplate'            , # Open XML Template
    'xlOpenXMLTemplateMacroEnabled', # Open XML Template Macro Enabled
    'xlOpenXMLWorkbook'            , # Open XML Workbook
    'xlOpenXMLWorkbookMacroEnabled', # Open XML Workbook Macro Enabled
    'xlSYLK'                       , # SYLK
    'xlTemplate'                   , # Template
    'xlTemplate8'                  , # Template 8
    'xlTextMac'                    , # Macintosh Text
    'xlTextMSDOS'                  , # MSDOS Text
    'xlTextPrinter'                , # Printer Text
    'xlTextWindows'                , # Windows Text
    'xlUnicodeText'                , # Unicode Text
    'xlWebArchive'                 , # Web Archive
    'xlWJ2WD1'                     , # WJ2WD1
    'xlWJ3'                        , # WJ3
    'xlWJ3FJ3'                     , # WJ3FJ3
    'xlWK1'                        , # WK1
    'xlWK1ALL'                     , # WK1ALL
    'xlWK1FMT'                     , # WK1FMT
    'xlWK3'                        , # WK3
    'xlWK3FM3'                     , # WK3FM3
    'xlWK4'                        , # WK4
    'xlWKS'                        , # Worksheet
    'xlWorkbookDefault'            , # Workbook default
    'xlWorkbookNormal'             , # Workbook normal
    'xlWorks2FarEast'              , # Works2 FarEast
    'xlWQ1'                        , # WQ1
    'xlXMLSpreadsheet'             , # XML Spreadsheet
    ]

xl = win32com.client.gencache.EnsureDispatch( "Excel.Application")
'''if you use Dispatch( 'Excel.Application') without having run makepy first,
    the constants from XlFileFormats will not be available.
    See
    http://docs.activestate.com/activepython/2.4/pywin32/html/com/win32com/HTML/GeneratedSupport.html
    http://docs.activestate.com/activepython/2.4/pywin32/html/com/win32com/HTML/QuickStartClientCom.html
    '''
app = xl.Application
app.Visible = 1
book = app.Workbooks.Add(); book.Activate()
print 'DefaultSaveFormat:', app.DefaultSaveFormat

# you cannot access the constants until AFTER you have dispatched excel
constants = win32com.client.constants

print
app.DisplayAlerts = False
for formatName in XlFileFormats:
    formatNum = getattr( constants, formatName)
    print '%-35s: %5d,' % ( formatName, formatNum),
    try: book.SaveAs( r'C:\excel_file_formats\xlbook', formatNum)
    except Exception: print 'could not save this format'
    else:
        wbname, wbext = splitext( book.Name)
        print '"%s"' % ( wbext)
        del wbname, wbext
    #~ raw_input( '    paused')

app.Quit()

Вот результат:

DefaultSaveFormat: 51

xlAddIn                            :    18, ".xls"
xlAddIn8                           :    18, ".xls"
xlCSV                              :     6, ".csv"
xlCSVMac                           :    22, ".csv"
xlCSVMSDOS                         :    24, ".csv"
xlCSVWindows                       :    23, ".csv"
xlCurrentPlatformText              : -4158, ".txt"
xlDBF2                             :     7, could not save this format
xlDBF3                             :     8, could not save this format
xlDBF4                             :    11, could not save this format
xlDIF                              :     9, ".dif"
xlExcel12                          :    50, ".xlsb"
xlExcel2                           :    16, could not save this format
xlExcel2FarEast                    :    27, could not save this format
xlExcel3                           :    29, could not save this format
xlExcel4                           :    33, could not save this format
xlExcel4Workbook                   :    35, could not save this format
xlExcel5                           :    39, ".xls"
xlExcel7                           :    39, ".xls"
xlExcel8                           :    56, ".xls"
xlExcel9795                        :    43, could not save this format
xlHtml                             :    44, ".htm"
xlIntlAddIn                        :    26, could not save this format
xlIntlMacro                        :    25, could not save this format
xlOpenDocumentSpreadsheet          :    60, ".ods"
xlOpenXMLAddIn                     :    55, ".ods" !!! this one is not right !!!
xlOpenXMLTemplate                  :    54, ".xltx"
xlOpenXMLTemplateMacroEnabled      :    53, ".xltm"
xlOpenXMLWorkbook                  :    51, ".xlsx"
xlOpenXMLWorkbookMacroEnabled      :    52, ".xlsm"
xlSYLK                             :     2, ".slk"
xlTemplate                         :    17, ".xlt"
xlTemplate8                        :    17, ".xlt"
xlTextMac                          :    19, ".txt"
xlTextMSDOS                        :    21, ".txt"
xlTextPrinter                      :    36, ".prn"
xlTextWindows                      :    20, ".txt"
xlUnicodeText                      :    42, ""
xlWebArchive                       :    45, ".mht"
xlWJ2WD1                           :    14, could not save this format
xlWJ3                              :    40, could not save this format
xlWJ3FJ3                           :    41, could not save this format
xlWK1                              :     5, could not save this format
xlWK1ALL                           :    31, could not save this format
xlWK1FMT                           :    30, could not save this format
xlWK3                              :    15, could not save this format
xlWK3FM3                           :    32, could not save this format
xlWK4                              :    38, could not save this format
xlWKS                              :     4, could not save this format
xlWorkbookDefault                  :    51, ".xlsx"
xlWorkbookNormal                   : -4143, ".xls"
xlWorks2FarEast                    :    28, could not save this format
xlWQ1                              :    34, could not save this format
xlXMLSpreadsheet                   :    46, ".xml"

Я не знаю, почему он не может сохранить некоторые форматы; но они не кажутся очень распространенными или полезными.

Кроме того, формат xlOpenXMLAddIn очень странный. Он сообщает и расширение ".ods" - но это не то, что на самом деле сохраняет. Если вы удалите какие-либо файлы, которые вы создали, измените код, чтобы он запускался только один раз в формате xlOpenXMLAddIn.

import win32com
from os.path import splitext
from time import sleep

xl = win32com.client.gencache.EnsureDispatch( "Excel.Application")
app = xl.Application
app.Visible = 1
book = app.Workbooks.Add(); book.Activate()
constants = win32com.client.constants

formatName = 'xlOpenXMLAddIn'
formatNum = getattr( constants, formatName)
print 'test_file_format: %s > %s' % ( formatName, formatNum)

app.DisplayAlerts = False
try: book.SaveAs( r'C:\excel_file_formats\xlbook', formatNum)
except Exception: print 'could not save this format'
else:
    wbname, wbext = splitext( book.Name)
    print '"%s" > "%s"' % ( wbname, wbext)

Вы получаете это:

test_file_format: xlOpenXMLAddIn > 55
"Book1" > ""

Создаваемый файл будет называться «xlbook.xlam»; но в строке заголовка Excel написано «Book1 - Microsoft Excel». Поэтому я не уверен, что происходит с этим. Во всяком случае, это не кажется очень полезным форматом.

person GarybCoder    schedule 16.11.2012