I want to build a hierarchical dictionary structure in C# from an Excel data sheet. The structure should look like this:
{
"Data": {
survey_id: {
"SurveyParameter": {},
"SurveySetting": {},
"Boreholes": {
borehole_id: {
"BoreholeParameter": {},
"BoreholeSetting": {},
"Layers": {
"Geology": {
layer_id: {"Parameter": {}, "LayerSetting": {}}
},
"Contamination": {
layer_id: {"Parameter": {}, "LayerSetting": {}}
},
},
}
},
}
}
}
"""
An example image of Excel data sheet from which the dictionary structure is to be built is provided here:
I have built a dictionary structure that looks like this second image (below). But I want to convert it to the hierarchical structure, shown at the top.
here is the text format of the dictionary saved as json file:
"3": {
"(SurveyParameter, SurveyId)": "[Company-Year]",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "[UTM, Revit]",
"(BoreholeParameter, BoreholeId)": null,
"(BoreholeSetting, AllowOverwrite)": "[True / False (default)]",
"(BoreholeSetting, Easting)": "[m] (X-Coordinate)",
"(BoreholeSetting, Northing)": "[m] (Y-Coordinate)",
"(BoreholeSetting, Elevation)": "[m] (Z-Coordinate)",
"(BoreholeParameter, BoreholeDiameter)": "[m] (default 0.4 m)",
"(Parameter, LayerId)": null,
"(Parameter, InputLayerStartDepth)": "(automatically filled)",
"(Parameter, InputLayerEndDepth)": "[m] (relative to coordinate)",
"(LayerSetting, SoilType)": "(pre-defined)",
"(Parameter, HomogeneousAreaSoil)": "(pre-defined)",
"(Parameter, SoilDescription)": null
},
"4": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_1",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 1.7,
"(LayerSetting, SoilType)": "A",
"(Parameter, HomogeneousAreaSoil)": "A",
"(Parameter, SoilDescription)": "G, s, u'"
},
"5": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_2",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 2.2,
"(LayerSetting, SoilType)": "A",
"(Parameter, HomogeneousAreaSoil)": "A",
"(Parameter, SoilDescription)": "G, s, u'"
},
"6": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_3",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 2.3,
"(LayerSetting, SoilType)": "Bohrhindernis",
"(Parameter, HomogeneousAreaSoil)": "Bohrhindernis",
"(Parameter, SoilDescription)": "Bohrhindernis"
I used the following code to build the dictionary in second image:
public void ExcelReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
Dictionary<string,Dictionary<(object, object), object>> rows = new Dictionary<string,Dictionary<(object, object), object>> ();
foreach (DataTable table in tables)
{
//DataRow selectedRow = table.Rows[3];
//DataRow newRow = table.NewRow();
//newRow.ItemArray = selectedRow.ItemArray; // copy data
//table.Rows.Remove(selectedRow);
//table.Rows.InsertAt(newRow, 3 + 1 / -1);
//table.Rows.Remove(table.Rows[0]);
Dictionary<(object, object), object> row;
foreach (DataRow dr in table.Rows)
{
row = new Dictionary<(object, object), object>();
foreach (DataColumn col in table.Columns)
{
object FirstcolName = table.Rows[0][col.ColumnName].ToString(); //index the first row with the column name
object SecondcolName = table.Rows[1][col.ColumnName].ToString(); //index the 2nd row with the column name
//string 3rdcolname = table.Rows[3][col.ColumnName].ToString(); //index the 2nd row with the column name
// Tuple<string,string> column_name_keys = new Tuple<string,string>(FirstcolName.ToString(), SecondcolName.ToString());
//col.ColumnName = column_name_keys;
// table.Rows[0].Delete();
row.Add((FirstcolName, SecondcolName), dr[col]); //add the column names as keys and data as values in the dicttionary.using a tuple of two column headers as key
}
int index = table.Rows.IndexOf(dr); //indexing eachrow to cnvert the value in each row to string
rows.Add(index.ToString(), row); //converting to string
}
string json = JsonConvert.SerializeObject(rows, Formatting.Indented);
File.WriteAllText(@"D:\Data\test.json", json);
}
}
}
Posting the developed code for people who might need it or might be stuck in a similar problem. This code below works for the most part as it makes the dictionary structure. However it needs to be improved with introduction of Flexible nested dictionaries that can take any types of values(including Dictionaries). This one generates the Survey_level Dictionary atleast: The nested borehole dictionary structure can only be added when we have a class that combines
Boreholes Dictionary, SurveyParameter Dictionary & SurveySetting Dictionary...
EDIT:
The following code has achieved the structure shown above in the question description. I hope it helps anyone who is stuck in this problem.