---
# System prepended metadata

title: CSV轉檔程式(手刻)
tags: [規格書]

---

# 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}");
        }
    }
}
```