2016-09-21 8 views
1

postgresqlビュー\ 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

私はどのように知ることができるでしょうか?もちろん、答えは「はい、あなたはそれを一般的にすることができます」です。どのように全く違うことですか?私は列の実際の順序を得るために可能な以上のことを推測します。 al。 SQLProviderを直接使用するのではなく、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 

ヴァルて:DataRecリスト= [{DT = 2016年9月27日午前0時00分00秒。 ADAY = "火曜日"; ID = 8L;}; ID = 8L;}; {DT = 2016/09/26 00:00:00; ADAY = "Monday"; ID = 9L;}; ID = 9L;}; {DT = 2016/09/25 00:00:00; ADAY = "Sunday";