【问题标题】:How can I create or read OpenOffice spreadsheets from Perl?如何从 Perl 创建或读取 OpenOffice 电子表格?
【发布时间】:2008-11-10 15:10:26
【问题描述】:

在 Perl 中创建和读取 OpenOffice 电子表格的好方法是什么?

【问题讨论】:

    标签: perl openoffice.org spreadsheet


    【解决方案1】:

    我认为 Open Office 原生文档格式基于 OpenDocument 规范,基本上是一种 zip 压缩的 XML 格式。这是真的,您可能可以使用您选择的 perl XML 操作工具来操作它。

    另外,Open Office OpenDocument Connector suite of modules on the CPAN 为 OpenDocument 规范提供高级 API。

    据我所知,这些模块中的表格方法应该允许在 OO Calc 文档中读取和写入数据。

    【讨论】:

    • @Brad Gilbert : 这和我的链接不一样吗?
    • @cms:Brad 的链接指向发行版而不是特定版本。这被认为是更好的形式。见*.com/questions/43758/…。我已相应地编辑了您的帖子。
    • @Michael Carman:谢谢,这比评论更清楚。很有道理。
    【解决方案2】:

    我使用OpenOffice::OOCBuilder 创建大型颜色编码表。非常喜欢。 对于更简单的任务,我经常使用任何电子表格程序都可以轻松打开的纯 CSV 格式

    但是,您可能会选择 Excel 的东西来与其他人兼容。

    【讨论】:

      【解决方案3】:

      OpenOffice 支持多种格式,如果您正在寻找可以读/写与 Excel 兼容的电子表格的内容,请查看Spreadsheet::ParseExcel 进行阅读,Spreadsheet::WriteExcel 进行写作。两个我都用过,很成熟,效果很好。

      【讨论】:

        【解决方案4】:

        这是 2.4 版本,因为最新版本不稳定。尽管有时它确实适用于最新版本。这将允许 Calc 中的实时 DDE 功能,而不是操作文件。这是在 XP 上使用 Cygwin Perl,但应该与其他人一起使用。我只想说 Excel VBA 编程 API 好 10 倍,混乱少 10 倍。这很糟糕。

        [代码]

        use Win32::OLE;
        
        Win32::OLE->Option(Warn => 3); # Turn on warnings for easier debugging
        
        #Win32::OLE->GetActiveObject
        # Get the currently running process or create a new one
        $objServiceManager = Win32::OLE->GetActiveObject("com.sun.star.ServiceManager") || Win32::OLE->new("com.sun.star.ServiceManager") || die "CreateObject: $!"; 
        
        $Stardesktop = $objServiceManager->createInstance("com.sun.star.frame.Desktop");
        
        # $Stardesktop->terminate();exit; # will kill ALL OpenOffice docs!!!
        # Doc = StarDesktop.loadComponentFromURL(sURL, "_default", 0, aMediaDesc)
        
        $propValue[0] = $objServiceManager->Bridge_GetStruct("com.sun.star.beans.PropertyValue");
        $propValue[0]->{Name} = "Hidden"; # This does not work!
        $propValue[0]->{Value} = 1;
        
        #Open the file and update its links if you have DDE links in your file
        $propValue[1] = $objServiceManager->Bridge_GetStruct("com.sun.star.beans.PropertyValue");
        $propValue[1]->{Name} = "UpdateDocMode";
        $propValue[1]->{Value} = 3; # com.sun.star.document.UpdateDocMode.FULL_UPDATE
        
        $calc = $Stardesktop->loadComponentfromUrl("file:///C:/Documents and Settings/Chloe/Desktop/MyFile.ods", "MyCalc", 0, \@propValue );
        # load a new blank spreadsheet
        $calc = $Stardesktop->loadComponentFromURL( "private:factory/scalc", "_blank", 0, [] );
        
        # How to hide, as loading the document hidden does not work.
        $calc->getCurrentController->getFrame->getContainerWindow()->setVisible(0);
        
        $oSheet = $calc->getSheets->getByIndex(0);
        
        # how to execute an UNO command, such as menu items
        # http://wiki.services.openoffice.org/wiki/Framework/Article/OpenOffice.org_2.x_Commands
        $frame = $calc->getCurrentController->getFrame;
        $dispatchHelper = $objServiceManager->createInstance("com.sun.star.frame.DispatchHelper");
        $dispatchHelper->executeDispatch(
            $frame, 
            ".uno:CalculateHard",
            #".uno:UpdateAll", 
            #".uno:UpdateAllLinks", 
            #".uno:DataAreaRefresh",
            "_self",
            0,
            []
        );
        
        
        $row = 5;
        $cellValue = $oSheet->getCellByPosition(0, $row)->getString(); # get a cell value
        
        # sort in decending order
        $range = $oSheet->getCellRangeByName("A1:P$row");
        $fields[0] = $objServiceManager->Bridge_GetStruct("com.sun.star.table.TableSortField");
        $fields[0]->{Field} = 7; # column number
        $fields[0]->{IsAscending} = 0;
        $unoWrap = $objServiceManager->Bridge_GetValueObject;
        $unoWrap->Set ("[]com.sun.star.table.TableSortField", \@fields);
        $sortDx = $range->createSortDescriptor();
        $sortDx->[0]->{Name} = "ContainsHeader";
        $sortDx->[0]->{Value} = 1;
        $sortDx->[3]->{Name} = "SortFields";
        $sortDx->[3]->{Value} = $unoWrap;
        #$sortDx->[3]->{Value} = \@fields; # You would think this would work? It doesn't.
        $range->sort($sortDx);
        
        
        # create a new sheet to paste to
        $calc->getSheets->insertNewByName("NewSheet", 1 );
        $sheet2 = $calc->getSheets->getByIndex(1);
        $calc->CurrentController->Select($sheet2);
        
        # copy row
        $pasteHere = $sheet2->getCellByPosition(0, 0)->CellAddress;
        $copyRange = $oSheet->getCellRangeByName("A1:Q1")->RangeAddress;
        $oSheet->copyRange($pasteHere, $copyRange);
        
        $cellValue = $sheet2->getCellByPosition(16, $row)->getValue()); # get cell value as integer
        $date = $sheet2->getCellByPosition(5, $row)->getString(); # must get dates as strings
        
        $calc->getCurrentController->getFrame->getContainerWindow()->setVisible(1); # set visible
        $calc->close(0); # close program window
        #print Win32::OLE->LastError, "\n";
        

        [/代码]

        【讨论】: