2016-07-25 26 views
0

Foxpro中的任何命令都會將DBF轉換爲特定的Excel工作表。 我有三個DBF(dbf_1,dbf_2,dbf_3)。我當前的程序使用將文件轉換爲「filename.xls」類型fox2x,然後手動將所有表格合併到一個excel中。對我而言,我使用的這種方法是可以的,但如果他們有20個或更多的dbf,我會整合。他們在foxpro中的任何命令都會將dbf轉換爲一個excel文件。我已經使用foxpro自動化,但它會減慢速度。COPY TO excel foxpro中的工作表

回答

3

不,沒有。

也「複製到......鍵入fox2x」。雖然比其他許多類型的選擇(如csv和xls)更好,但在有更好的方法時不應該選擇。

你說的是自動化很慢,但不知道你是否真的發現自動化緩慢,或者你是否已經嘗試過,不應該用它來傳輸數據到Excel。下面的示例使用我的「vfp2excel」函數和自動化的變體之一。它在2.5秒內在我的機器上傳輸樣品客戶,員工,訂單,OrdItems和產品數據。如果你真的是想慢則沒有骰子,否則這裏的樣本:

* These represent complex SQL as a sample 
Select emp_id,First_Name,Last_Name,; 
    Title,Notes ; 
    from (_samples+'\data\employee') ; 
    into Cursor crsEmployee ; 
    readwrite 
Replace All Notes With Chrtran(Notes,Chr(13)+Chr(10),Chr(10)) 

Select cust_id,company,contact,Title,country,postalcode ; 
    from (_samples+'\data\customer') ; 
    into Cursor crsCustomer ; 
    nofilter 

Select * ; 
    from (_samples+'\data\orders') ; 
    into Cursor crsOrders ; 
    nofilter 

Select * ; 
    from (_samples+'\data\orditems') ; 
    into Cursor crsOrderDetail ; 
    nofilter 

Select * ; 
    from (_samples+'\data\products') ; 
    into Cursor crsProducts ; 
    nofilter 

* Now we want to get these on 3 sheets 
* Sheet1: Employees only 
* Sheet2: Customers only 
* Sheet3: Orders, ordItems, Products layed out horizontally 

Local oExcel 
oExcel = Createobject("Excel.Application") 
With oExcel 
    .DisplayAlerts = .F. 
    .Workbooks.Add 
    .Visible = .T. 
    With .ActiveWorkBook 
     For ix = 1 To 3 && We want 3 Sheets 
      If .sheets.Count < m.ix 
       .sheets.Add(,.sheets(.sheets.Count)) && Add new sheets 
      Endif 
     Endfor 
     * Name the sheets 
     .WorkSheets(1).Name = "Employees" 
     .WorkSheets(2).Name = "Customers" 
     .WorkSheets(3).Name = "Order, OrderDetail, Products" && max sheetname is 31 chars 

     * Start sending data 
     * First one has headers specified 
     VFP2Excel('crsEmployee', .WorkSheets(1).Range("A1"), ; 
      "Id,First Name,Last Name,Employee Title,Comments about employee") && To sheet1, start at A1 
     VFP2Excel('crsCustomer', .WorkSheets(2).Range("A1")) && To sheet2, start at A1 
     VFP2Excel('crsOrders',  .WorkSheets(3).Range("A1")) && To sheet3, start at A1 
     * Need to know where to put next 
     * Leave 2 columns empty - something like 'G1' 
     lcRange = _GetChar(.WorkSheets(3).UsedRange.Columns.Count + 3) + '1' 
     * To sheet3, start at next to previous 
     VFP2Excel('crsOrderDetail', .WorkSheets(3).Range(m.lcRange)) 

     lcRange = _GetChar(.WorkSheets(3).UsedRange.Columns.Count + 3) + '1' 
     * To sheet3, start at next to previous 
     VFP2Excel('crsProducts', .WorkSheets(3).Range(m.lcRange)) 

     #Define xlJustify           -4130 
     #Define xlTop            -4160 

     * I just happen to know notes in at column 5 from SQL 
     * No need to query from excel to keep code simple 
     * Lets format that column specially instead of leaving 
     * at the mercy of Excel's autofitting 
     .WorkSheets(1).UsedRange.VerticalAlignment = xlTop && set all to top 
     With .WorkSheets(1).Columns(5) 
      .ColumnWidth = 80 && 80 chars width 
      .WrapText = .T. 
      *  .HorizontalAlignment = xlJustify && doesn't work good always 
     Endwith 

     * Finally some cosmetic stuff 
     For ix=1 To 3 
      With .WorkSheets(m.ix) 
       .Columns.AutoFit 
       .Rows.AutoFit 
      Endwith 
     Endfor 

     .WorkSheets(1).Activate 
    Endwith 
Endwith 


* Author: Cetin Basoz 
* This is based on earlier VFP2Excel function codes 
* that has been published on the internet, at various sites 
* since 2001. Not to be messed with others' code who named the same but has 
* nothing to do with the approaches taken here (unless copy & pasted and claimed 
* to be their own work, <s> that happens). 
Procedure VFP2Excel(tcCursorName, toRange, tcHeaders, tnPrefferredWidthForMemo) 
    * tcCursorName 
    * toRange 
    * tcHeaders: Optional. Defaults to field headers 
    * tnPrefferredWidthForMemo: Optional. Default 80 
    * Function VFP2Excel 
    tcCursorName = Evl(m.tcCursorName,Alias()) 
    tnPrefferredWidthForMemo = Evl(m.tnPrefferredWidthForMemo,80) 
    Local loConn As AdoDB.Connection, loRS As AdoDB.Recordset,; 
     lcTemp,lcTempDb, oExcel,ix, lcFieldName, lcHeaders 

    lnSelect = Select() 
    lcTemp = Forcepath(Sys(2015)+'.dbf',Sys(2023)) 
    lcTempDb = Forcepath(Sys(2015)+'.dbc',Sys(2023)) 

    Create Database (m.lcTempDb) 
    Select * From (m.tcCursorName) Into Table (m.lcTemp) Database (m.lcTempDb) 

    Local Array aMemo[1] 
    Local nMemoCount 
    nMemoCount = 0 
    lcHeaders = '' 
    For ix = 1 To Fcount() 
     lcFieldName = Field(m.ix) 
     If Type(Field(m.ix))='M' 
      nMemoCount = m.nMemoCount + 1 
      Dimension aMemo[m.nMemoCount] 
      aMemo[m.nMemoCount] = m.ix 
      Replace All &lcFieldName With Chrtran(&lcFieldName,Chr(13)+Chr(10),Chr(10)) 
     Endif 
     lcHeaders = m.lcHeaders + Iif(Empty(m.lcHeaders),'',',')+Proper(m.lcFieldName) 
    Endfor 
    tcHeaders = Evl(m.tcHeaders,m.lcHeaders) 

    Use In (Juststem(m.lcTemp)) 
    Close Databases 
    Set Database To 

    loStream = Createobject('AdoDb.Stream') 
    loConn = Createobject('ADODB.Connection') 
    loRS = Createobject("ADODB.Recordset") 
    loConn.ConnectionString = "Provider=VFPOLEDB;Data Source="+m.lcTempDb 
    loConn.Open() 
    loRS = loConn.Execute("select * from "+m.lcTemp) 
    loRS.Save(loStream) 
    loRS.Close 
    loConn.Close 
    Erase (m.lcTemp) 

    * Use first row for headers 
    Local Array aHeader[1] 

    loRS.Open(loStream) 
    toRange.Offset(1,0).CopyFromRecordSet(loRS) && Copy data starting from headerrow + 1 

    Set Safety Off 
    Delete Database (m.lcTempDb) Deletetables 

    Select (m.lnSelect) 

    For ix=1 To Iif(!Empty(m.tcHeaders), ; 
      ALINES(aHeader, m.tcHeaders,1,','), ; 
      loRS.Fields.Count) 
     toRange.Offset(0,m.ix-1).Value = ; 
      Iif(!Empty(m.tcHeaders), ; 
      aHeader[m.ix], ; 
      Proper(loRS.Fields(m.ix-1).Name)) 
     toRange.Offset(0,m.ix-1).Font.Bold = .T. 
    Endfor 

    #Define xlJustify           -4130 
    #Define xlTop            -4160 
    * This part is cosmetic 
    toRange.WorkSheet.Activate 
    With toRange.WorkSheet.UsedRange 
     .VerticalAlignment = xlTop && set all to top 
     For ix=1 To m.nMemoCount 
      With .Columns(aMemo[m.ix]) 
       .ColumnWidth = m.tnPrefferredWidthForMemo && 80 chars width 
       .WrapText = .T. 
      Endwith 
     Endfor 
     .Columns.AutoFit 
     .Rows.AutoFit 
    Endwith 
Endproc 

* Return A, AA, BC etc noation for nth column 
Function _GetChar 
    Lparameters tnColumn && Convert tnvalue to Excel alpha notation 
    If m.tnColumn = 0 
     Return "" 
    Endif 
    If m.tnColumn <= 26 
     Return Chr(Asc("A")-1+m.tnColumn) 
    Else 
     Return _GetChar(Int(Iif(m.tnColumn % 26 = 0,m.tnColumn - 1, m.tnColumn)/26)) + ; 
      _GetChar((m.tnColumn-1)%26+1) 
    Endif 
Endfunc 
+0

謝謝你的幫助。我在Foxpro自動化方面的問題是,在我的報告excel中,它們是很多公式,爲什麼它很慢。現在我正在思考如何將某張表複製到Foxpro Automation工作中,以便在Excel中傳輸數據後,我會將帶有公式的表單複製到工作表中。 – Vic

+0

我想你沒看過這段代碼。您可以將公式作爲模板保存在工作表中,並根據該模板添加新的Excel工作簿,或者可以一次爲多個單元格編寫公式。或者只需要一個命令就可以將工作表從另一個工作簿複製到另一個工作簿。 –

0

這就是我一直在尋找:-)我與我的Excel自動化編程的知識試圖Visual FoxPro中但總是有錯誤。我的任務是從一個大遊標創建「n」表格,我想解析關於客戶從遊標中選擇屬性名稱以獲得「n」表格。此示例用於3個遊標和3個表格,它是通用的。但我需要這個「N」遊標一個屬性哪個客戶選擇到不同得到「N」表在一個Excel文件。所以現在我有動態程序。我定製了這段代碼並解決了我想要結束大約4天的問題。所以再次感謝你的這個代碼,當然我不會修改VFP2Excel程序,並寫在別的地方我的名字。感謝幫助 !

0

沒有本地 VFP功能,要做到這一點,但是,有是有一個類的真棒開源項目,它將使這很容易:

VFPx工作簿XLSX(見這裏) :https://vfpx.codeplex.com/wikipage?title=XLSXWorkbook

它有3個神奇的功能,將做的正是你問什麼:

  • CreateWorkbook()
  • AddSheet()
  • SaveTableToWorkbook()

(重複命令2和上述3爲要創建的每個DBF /片)

是公用54頁的PDF和代碼記錄樣本,解釋你需要知道的一切。