# CSV轉檔程式 ## 準備工作 1. 安裝 Visual Studio 開發環境 2. 下載並安裝 .NET Core SDK[下載連結](https://dotnet.microsoft.com/en-us/download) 3. 準備一個包含病人資料的 CSV 檔案 ```CSV= Name,Gender,BirthDate,Address,Telephone John Doe,M,1970-05-25,123 Main St,Anytown CA 12345,+1-555-0123 Jane Smith,F,1985-11-30,456 Oak Rd,Someville VA 67890,+1-987-6543 ``` 4. 道專案目錄執行以下命令來建立一個新的 console 專案: ``` dotnet new console -n CsvToFhir ``` 這將在名為 CsvToFhir 的文件夾中建立一個新專案,包含基本的 Program.cs 和 CsvToFhir.csproj。可把先前準備的CSV放在Program.cs這層資料夾中 5. 安裝 `CsvHelper` ``` dotnet add package CsvHelper ``` 6. 將範例程式碼放入Program.cs中 ## 範例程式碼(以Patient為例) ```chsrp= using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text; using Hl7.Fhir.Model; using Hl7.Fhir.Serialization; class Program { static void Main(string[] args) { // CSV檔案路徑和FHIR伺服器URL string csvFilePath = @"data.csv"; string fhirServerUrl = "https://fhir.tcumi.com:58443/r5/fhir"; // 讀取CSV文件 string[] csvLines = File.ReadAllLines(csvFilePath); // 解析CSV標頭 string[] headers = csvLines[0].Split(','); // 創建FHIR資源列表 List<Patient> patients = new List<Patient>(); // 將CSV數據映射到FHIR資源 for (int i = 1; i < csvLines.Length; i++) { string[] values = csvLines[i].Split(','); var patient = new Patient(); for (int j = 0; j < headers.Length; j++) { switch (headers[j].ToLower()) { case "name": var names = new List<HumanName>(); names.Add(new HumanName { Text = values[j] }); patient.Name = names; break; case "gender": patient.Gender = values[j] == "M" ? AdministrativeGender.Male : AdministrativeGender.Female; break; case "birthdate": patient.BirthDate = values[j]; break; case "address": patient.Address.Add(new Address { Text = values[j] }); break; case "telephone": patient.Telecom.Add(new ContactPoint { System = ContactPoint.ContactPointSystem.Phone, Value = values[j] }); break; } } patients.Add(patient); } // 序列化FHIR資源 var fhirSerializer = new FhirJsonSerializer(new SerializerSettings { Pretty = true }); // POST到FHIR伺服器 var client = new HttpClient(); foreach (var patient in patients) { patient.Id = null; var body = fhirSerializer.SerializeToString(patient); var response = client.PostAsync($"{fhirServerUrl}/Patient", new StringContent(body, Encoding.UTF8, "application/fhir+json")).Result; if (response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync().Result; Console.WriteLine($"Patient 上傳成功,回應內容:"); Console.WriteLine(content); } else { var errorContent = response.Content.ReadAsStringAsync().Result; Console.WriteLine($"錯誤: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine(errorContent); } } // 獲取最近上傳的Patient資源 var getResponse = client.GetAsync($"{fhirServerUrl}/Patient?_count=1").Result; if (getResponse.IsSuccessStatusCode) { var getContent = getResponse.Content.ReadAsStringAsync().Result; Console.WriteLine("最近上傳的Patient資源:"); Console.WriteLine(getContent); } else { Console.WriteLine($"獲取Patient資源失敗: {getResponse.StatusCode} - {getResponse.ReasonPhrase}"); } } } ``` 9. 將 `csvFilePath` 變數的值替換為專案的 CSV 檔案路徑。 10. 將 `fhirServerUrl` 變數的值替換為專案的 FHIR 伺服器的基礎 URL。 11. 建置專案 ``` dotnet build ``` 13. 運行專案 ``` dotnet run ``` 14. 執行結果 ![螢幕擷取畫面 2024-05-09 043057](https://hackmd.io/_uploads/ryuVzDtzC.png) ![image](https://hackmd.io/_uploads/HkZdGPKG0.png) # 變更ressource方法 ## 接下來會說明如何將這份程式的resource改成observation - 以下是需要調整的地方 ![1715201065892](https://hackmd.io/_uploads/SJaY4DKMR.jpg) ![1715201234696](https://hackmd.io/_uploads/B10yHvYz0.jpg) ## 完整程式碼範例 ```cshrp= using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text; using System.Text.Json; class Program { static void Main(string[] args) { // CSV檔案路徑和FHIR伺服器URL string csvFilePath = @"observations.csv"; string fhirServerUrl = "https://fhir.tcumi.com:58443/r5/fhir"; // 讀取CSV文件 string[] csvLines = File.ReadAllLines(csvFilePath); // 解析CSV標頭 string[] headers = csvLines[0].Split(','); // 創建Observation資源列表 List<Dictionary<string, object>> observations = new List<Dictionary<string, object>>(); // 將CSV數據映射到Observation資源 for (int i = 1; i < csvLines.Length; i++) { string[] values = csvLines[i].Split(','); var observation = new Dictionary<string, object>(); // 添加resourceType屬性 observation["resourceType"] = "Observation"; for (int j = 0; j < headers.Length; j++) { switch (headers[j].ToLower()) { case "code": observation["code"] = new Dictionary<string, object> { ["coding"] = new List<Dictionary<string, string>> { new Dictionary<string, string> { ["system"] = "http://loinc.org", ["code"] = values[j] } } }; break; case "value": observation["valueQuantity"] = new Dictionary<string, object> { ["value"] = double.Parse(values[j]), ["unit"] = "mg/dL", ["system"] = "http://unitsofmeasure.org", ["code"] = "mg/dL" }; break; case "date": observation["effectiveDateTime"] = values[j]; break; case "subject": observation["subject"] = new Dictionary<string, string> { ["reference"] = $"Patient/{values[j]}" }; break; } } observations.Add(observation); } // 序列化Observation資源 var options = new JsonSerializerOptions { WriteIndented = true }; // POST到FHIR伺服器 var client = new HttpClient(); foreach (var observation in observations) { var body = JsonSerializer.Serialize(observation, options); var response = client.PostAsync($"{fhirServerUrl}/Observation", new StringContent(body, Encoding.UTF8, "application/fhir+json")).Result; if (response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync().Result; Console.WriteLine($"Observation 上傳成功,回應內容:"); Console.WriteLine(content); } else { var errorContent = response.Content.ReadAsStringAsync().Result; Console.WriteLine($"錯誤: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine(errorContent); } } // 獲取最近上傳的Observation資源 var getResponse = client.GetAsync($"{fhirServerUrl}/Observation?_count=1").Result; if (getResponse.IsSuccessStatusCode) { var getContent = getResponse.Content.ReadAsStringAsync().Result; Console.WriteLine("最近上傳的Observation資源:"); Console.WriteLine(getContent); } else { Console.WriteLine($"獲取Observation資源失敗: {getResponse.StatusCode} - {getResponse.ReasonPhrase}"); } } } ```