2016-09-21 94 views
1

我從postgresql view \ table中選擇並將值導出到excel文件中。F#SQLProvider列順序與表中的順序不匹配

Excel文件列順序必須是相同的表,但sqlProvider的與ABC順序選擇它們...

我的代碼是:

module ViewToExcel 

open System 
open System.IO 
//open Microsoft.Office.Interop.Excel 
open System.Drawing 
open Npgsql 
open FSharp.Data.Sql 
open OfficeOpenXml 
open Casaubon 
open NpgsqlTypes 

let [<Literal>] connectionString = @"Server=localhost;Database=db;User Id=postgres;Password=;" 
let [<Literal>] npgPath = @"..\packages\Npgsql.3.1.7\lib\net451" 

type sqlConnection = SqlDataProvider<ConnectionString = connectionString, 
             DatabaseVendor = Common.DatabaseProviderTypes.POSTGRESQL, 
             ResolutionPath = npgPath, 
             IndividualsAmount = 1000, 
             UseOptionTypes = true> 
let functionParseViewToExcel (excelPath:string, serverName:string, dbName:string) = 


     /////////////////////////////////Get Data Connection/////////////////////// 
     printf "connect to db\n" 

     let connectionUserString = @"Server="+serverName+";Database="+dbName+";User Id=postgres;Password=;" 

     let ctx = sqlConnection.GetDataContext(connectionUserString) 

     let weekCalcView = ctx.Public.CcVibeWeeklyCalculations 

     // weekCalcView|> Seq.toList 

     let weekCalcViewSeq = ctx.Public.CcVibeWeeklyCalculations|> Seq.toArray 

     ////////////////////////////////// Start Excel////////////////////////////// 

     let newExcelFile = FileInfo(excelPath + "cc_vibe_treatment_period_"+ DateTime.Today.ToString("yyyy_dd_MM")+".xlsx"); 

     if (newExcelFile.Exists) then 
      newExcelFile.Delete(); 

     let pck = new ExcelPackage(newExcelFile); 

     //Add the 'xxx' sheet 
     let ws = pck.Workbook.Worksheets.Add("xxx"); 

     //printf "success to start the excel file\n" 

     let mutable columNames = "blabla" 
     for col in weekCalcViewSeq.[0].ColumnValues do 
      let columnName = match col with |(a, _) -> a 
      //printf "a %A\n" columnName 
      let columnNamewithPsic = "," + columnName 
      columNames <- columNames + columnNamewithPsic 
     ws.Cells.[1, 1].LoadFromText(columNames.Replace("blabla,",""))|> ignore 

     ws.Row(1).Style.Fill.PatternType <- Style.ExcelFillStyle.Solid 
     ws.Row(1).Style.Fill.BackgroundColor.SetColor(Color.FromArgb(170, 170, 170)) 
     ws.Row(1).Style.Font.Bold <- true; 
     ws.Row(1).Style.Font.UnderLine <- true; 

     let mutable subject = weekCalcViewSeq.[0].StudySubjectLabel.Value // in order to color the rows according to subjects 
     let mutable color = 0 
     for row in 1.. weekCalcViewSeq.Length do 
      let mutable columValues = "blabla" 
      for col in weekCalcViewSeq.[row-1].ColumnValues do 
       let columnValue = match col with |(_, a) -> a 
       //printf "a %A\n" columnValue 
       match columnValue with 
       | null -> columValues <- columValues + "," + "" 
       | _ -> columValues <- columValues + "," + columnValue.ToString()    
      ws.Cells.[row + 1, 1].LoadFromText(columValues.Replace("blabla,",""))|> ignore 

      /////////////////////Color the row according to subject/////////////// 


      if (weekCalcViewSeq.[row - 1].StudySubjectLabel.Value = subject) then 
       if (color = 0) then 
        ws.Row(row + 1).Style.Fill.PatternType <- Style.ExcelFillStyle.Solid 
        ws.Row(row + 1).Style.Fill.BackgroundColor.SetColor(Color.FromArgb(255,255,204)) 
       else 
        ws.Row(row + 1).Style.Fill.PatternType <- Style.ExcelFillStyle.Solid 
        ws.Row(row + 1).Style.Fill.BackgroundColor.SetColor(Color.White) 
      else 
       subject <- weekCalcViewSeq.[row - 1].StudySubjectLabel.Value 
       if (color = 0) then 
        color <- 1 
        ws.Row(row + 1).Style.Fill.PatternType <- Style.ExcelFillStyle.Solid 
        ws.Row(row + 1).Style.Fill.BackgroundColor.SetColor(Color.White)     
       else 
        color <- 0 
        ws.Row(row + 1).Style.Fill.PatternType <- Style.ExcelFillStyle.Solid 
        ws.Row(row + 1).Style.Fill.BackgroundColor.SetColor(Color.FromArgb(255,255,204)) 

pck.Save() 

Excel的輸出字段是: bloating_avg,caps_fail,caps_success,date_of_baseline_visit,discomfort_avg等...

但是表中的順序並不相同。

有人可以幫助我嗎?

謝謝!

+3

這段代碼在任何方面都遠遠不能運行,因此......總的來說,如果你想按照特定順序列出這些列,可以明確地按照這個順序編寫它。 –

+0

難道我不能通用嗎?爲不同的列的每個視圖? – MRah

+3

我應該怎樣才能知道?當然,答案是「是的,你可以做到通用」。如何是完全不同的問題。我會猜測它更可能得到列等的實際順序。人。在某些方面,但可能不直接與SQLProvider。我不明白你爲什麼需要,所以... –

回答

2

您可以編寫一個小幫助函數,通過npgqsl提取字段(列)名稱。之後,您可以使用這個列名稱列表來創建您的Excel表格。 getColNames函數從DataReader中獲取它。很明顯,你可以進一步重構它,以獲得在表名作爲參數,等等

#r @"..\packages\SQLProvider.1.0.33\lib\FSharp.Data.SqlProvider.dll" 
#r @"..\packages\Npgsql.3.1.7\lib\net451\Npgsql.dll" 

open System 
open FSharp.Data.Sql 
open Npgsql 
open NpgsqlTypes 

let conn = new NpgsqlConnection("Host=localhost;Username=postgres;Password=root;Database=postgres;Pooling=false") 
conn.Open() 
let cmd = new NpgsqlCommand() 
cmd.Connection <- conn 

cmd.CommandText <- """ SELECT * FROM public."TestTable1" """ 
let recs = cmd.ExecuteReader() 

let getColNames (recs:NpgsqlDataReader) = 
    let columns = recs.GetColumnSchema() |> Seq.toList 
    columns |> List.map (fun x -> x.BaseColumnName) 

let colnames = getColNames recs 
//val colnames : string list = ["ID"; "DT"; "ADAY"] 

rec.Dispose() 
conn.Dispose() 

你可以看到,列名不按字母順序排列。您可以使用此列名稱列表以正確的順序查看記錄。或者直接使用Reader對象而不使用類型提供程序。

編輯:使用記錄映射表

還可以提取數據,使用所述類型提供,以所需的格式,由佈線了的類型,並且然後使用.MapTo<T>

type DataRec = { 
    DT:DateTime 
    ADAY:String 
    ID:System.Int64 
    } 

type sql = SqlDataProvider<dbVendor,connString2,"",resPath,indivAmount,useOptTypes> 
let ctx = sql.GetDataContext() 
let table1 = ctx.Public.TestTable1 
let qry = query { for row in table1 do 
        select row} |> Seq.map (fun x -> x.MapTo<DataRec>()) 
qry |> Seq.toList 

val it:DataRec list = [{DT = 2016/09/27 00:00:00; ADAY =「星期二」; ID = 8L;}; {DT = 2016/09/26 00:00:00; ADAY =「星期一」; ID = 9L;}; {DT = 2016/09/25 00:00:00; ADAY =「星期天」;