Пример #1
0
        /// <summary>
        /// Read in the APSIM header - headings/units and constants.
        /// </summary>
        /// <param name="inData">The in.</param>
        /// <exception cref="System.Exception">The number of headings and units doesn't match in file:  + _FileName</exception>
        private void ReadApsimHeader(StreamReaderRandomAccess inData)
        {
            StringCollection ConstantLines = new StringCollection();
            StringCollection HeadingLines  = new StringCollection();

            ReadApsimHeaderLines(inData, ref ConstantLines, ref HeadingLines);

            bool TitleFound = false;

            foreach (string ConstantLine in ConstantLines)
            {
                string Line    = ConstantLine;
                string Comment = StringUtilities.SplitOffAfterDelimiter(ref Line, "!");
                Comment.Trim();
                int PosEquals = Line.IndexOf('=');
                if (PosEquals != -1)
                {
                    string Name = Line.Substring(0, PosEquals).Trim();
                    if (Name.ToLower() == "title")
                    {
                        TitleFound = true;
                        Name       = "Title";
                    }
                    string Value = Line.Substring(PosEquals + 1).Trim();
                    string Unit  = string.Empty;
                    if (Name != "Title")
                    {
                        Unit = StringUtilities.SplitOffBracketedValue(ref Value, '(', ')');
                    }
                    _Constants.Add(new ApsimConstant(Name, Value, Unit, Comment));
                }
            }
            if (HeadingLines.Count >= 1)
            {
                if (IsCSVFile)
                {
                    HeadingLines[0] = HeadingLines[0].TrimEnd(',');
                    Headings        = new StringCollection();
                    Units           = new StringCollection();
                    Headings.AddRange(HeadingLines[0].Split(",".ToCharArray()));
                    for (int i = 0; i < Headings.Count; i++)
                    {
                        Headings[i] = Headings[i].Trim();
                        Units.Add("()");
                    }
                }
                else
                {
                    Headings = StringUtilities.SplitStringHonouringQuotes(HeadingLines[0], " \t");
                    Units    = StringUtilities.SplitStringHonouringQuotes(HeadingLines[1], " \t");
                }
                TitleFound = TitleFound || StringUtilities.IndexOfCaseInsensitive(Headings, "title") != -1;
                if (Headings.Count != Units.Count)
                {
                    throw new Exception("The number of headings and units doesn't match in file: " + _FileName);
                }
            }
            if (!TitleFound)
            {
                _Constants.Add(new ApsimConstant("Title", System.IO.Path.GetFileNameWithoutExtension(_FileName), "", ""));
            }
        }
Пример #2
0
        /// <summary>
        /// This is used to read an excel file, extracting header, unit and constant information
        /// </summary>
        public void OpenExcelReader()
        {
            _excelData = new DataTable();

            if ((_FileName.Length <= 0) || (_SheetName.Length <= 0))
            {
                return;
            }

            try
            {
                Units    = new StringCollection();
                Headings = new StringCollection();

                DataTable resultDt = ExcelUtilities.ReadExcelFileData(_FileName, _SheetName);

                if (resultDt == null)
                {
                    throw new Exception("There does not appear to be any data.");
                }

                int    posEquals, rowCount = -1;
                string coltext1, coltext2, coltext3, coltext4;
                string unit, name, value, comment;
                bool   titleFound = false;
                bool   dataFound  = false;
                bool   unitsFound = false;

                while (dataFound == false)
                {
                    rowCount++;
                    coltext1 = resultDt.Rows[rowCount][0].ToString().Trim();
                    coltext2 = resultDt.Rows[rowCount][1].ToString().Trim();
                    coltext3 = resultDt.Rows[rowCount][2].ToString().Trim();
                    coltext4 = resultDt.Rows[rowCount][3].ToString().Trim();

                    //Assumptions are made here about the data, based on the values in the first two columns:
                    // If they are both blank, then this is a blank line.
                    // If there is data in first column, but not second, then this is the header/constant details line
                    // If there is data in both columns, then this is the first of our data for the datatable, with
                    //   the first line being the column titles, and if the second line starts with a '(' then this is
                    //   a measurement line, otherwise we are looking at the actual data values.

                    //if no data only in columns 1 and 2, then it is a blank line
                    //if data only in columns 1, then it could be a comments line, and is ignored
                    //if data only in columns 1 & 2, then it is a constants row
                    //if data on 3 or more columns then is actual data
                    //all measurements (in both constants and data headings) are in brackets after name (title)

                    unit    = string.Empty;
                    name    = string.Empty;
                    value   = string.Empty;
                    comment = string.Empty;

                    posEquals = coltext1.IndexOf('!');
                    if (posEquals == 0)
                    {
                        //this is a comment line, and can be ignored
                        resultDt.Rows[rowCount].Delete();
                    }
                    else if (coltext1.Length == 0)
                    {
                        //if no data in column 1, then this is a blank row, need to make sure we remove these
                        resultDt.Rows[rowCount].Delete();
                    }
                    // Check for and handle "old style" constants
                    else if ((coltext1.Length > 0) && coltext2.Length == 0)
                    {
                        comment   = StringUtilities.SplitOffAfterDelimiter(ref coltext1, "!").Trim();
                        posEquals = coltext1.IndexOf('=');
                        if (posEquals != -1)
                        {
                            name = coltext1.Substring(0, posEquals).Trim();
                            if (name.ToLower() == "title")
                            {
                                titleFound = true;
                                name       = "Title";
                            }
                            value = coltext1.Substring(posEquals + 1).Trim();
                            if (name != "Title")
                            {
                                unit = StringUtilities.SplitOffBracketedValue(ref value, '(', ')');
                            }
                            _Constants.Add(new ApsimConstant(name, value, unit, comment));
                        }
                        resultDt.Rows[rowCount].Delete();
                    }
                    else if ((coltext1.Length > 0) && (coltext2.Length > 0) && (coltext4.Length == 0))
                    {
                        //the unit, if it exists, is after the title (name) of the constant
                        unit = StringUtilities.SplitOffBracketedValue(ref coltext1, '(', ')');

                        name = coltext1.Trim();
                        if (name.ToLower() == "title")
                        {
                            titleFound = true;
                            name       = "Title";
                        }

                        //now look at what is left in the first row
                        value = coltext2.Trim();

                        //comments are in column three - need to strip out any '!' at the start
                        if (coltext3.Length > 0)
                        {
                            comment = StringUtilities.SplitOffAfterDelimiter(ref coltext3, "!");
                            comment.Trim();
                        }
                        _Constants.Add(new ApsimConstant(name, value, unit, comment));
                        resultDt.Rows[rowCount].Delete();
                    }

                    //the first line that has data in the first 4 columns
                    else if ((coltext1.Length > 0) && (coltext2.Length > 0) && (coltext3.Length > 0) && (coltext4.Length > 0))
                    {
                        for (int i = 0; i < resultDt.Columns.Count; i++)
                        {
                            value = resultDt.Rows[rowCount][i].ToString();
                            if (value.Length > 0)
                            {
                                //extract the measurment if it exists, else need to create blank, and add to Units collection
                                unit = StringUtilities.SplitOffBracketedValue(ref value, '(', ')');
                                if (unit.Length <= 0)
                                {
                                    unit = "()";
                                }
                                else
                                {
                                    unitsFound = true;
                                }
                                Units.Add(unit.Trim());

                                //add the title(name to Units collection
                                Headings.Add(value.Trim());
                            }
                        }

                        resultDt.Rows[rowCount].Delete();
                        //we have got both headings and measurements, so we can exit the while loop
                        dataFound = true;
                    }
                    //to ensure that we never get stuck on infinite loop;
                    if (rowCount >= resultDt.Rows.Count - 1)
                    {
                        dataFound = true;
                    }
                }

                //make sure that the next row doesn't have '()' measurements in it
                coltext1  = resultDt.Rows[rowCount + 1][0].ToString().Trim();
                posEquals = coltext1.IndexOf('(');
                if (posEquals == 0)
                {
                    //this line contains brackets, SHOULD be DATA
                    if (unitsFound)
                    {
                        throw new Exception();
                    }
                    // but if we haven't already seen units,
                    // read units from this line
                    // (to support "old style" layouts)
                    else
                    {
                        for (int i = 0; i < resultDt.Columns.Count; i++)
                        {
                            Units[i] = resultDt.Rows[rowCount + 1][i].ToString();
                        }
                        resultDt.Rows[rowCount + 1].Delete();
                    }
                }

                //this will actually delete all of the rows that we flagged for delete (above)
                resultDt.AcceptChanges();

                //this is where we clone the current datatable, so that we can set the datatypes to what they should be,
                //based on the first row of actual data (Need to do this as cannot change datatype once a column as data).
                _excelData = resultDt.Clone();
                for (int i = 0; i < resultDt.Columns.Count; i++)
                {
                    _excelData.Columns[i].DataType = StringUtilities.DetermineType(resultDt.Rows[0][i].ToString(), Units[i]);
                }
                _excelData.Load(resultDt.CreateDataReader());

                //now do the column names, need to have data loaded before we rename columns, else the above won't work.
                for (int i = 0; i < resultDt.Columns.Count; i++)
                {
                    _excelData.Columns[i].ColumnName = Headings[i];
                }

                _FirstDate = GetDateFromValues(_excelData, 0);
                _LastDate  = GetDateFromValues(_excelData, _excelData.Rows.Count - 1);

                if (!titleFound)
                {
                    _Constants.Add(new ApsimConstant("Title", System.IO.Path.GetFileNameWithoutExtension(_FileName), "", ""));
                }
            }
            catch (Exception e)
            {
                throw new Exception(string.Format("The excel Sheet {0} is not in a recognised Weather file format." + e.Message.ToString(), _SheetName));
            }
        }
Пример #3
0
        /// <summary>
        /// Convert this file to a DataTable.
        /// </summary>
        /// <returns></returns>
        public DataTable ToTable(List <string> addConsts = null)
        {
            System.Data.DataTable data = new System.Data.DataTable();
            data.TableName = "Data";

            if (IsExcelFile == true)
            {
                data = ToTableFromExcel(addConsts);
            }
            else
            {
                ArrayList addedConstants = new ArrayList();

                StringCollection words = new StringCollection();
                bool             checkHeadingsExist = true;
                while (GetNextLine(inStreamReader, ref words))
                {
                    if (checkHeadingsExist)
                    {
                        for (int w = 0; w != ColumnTypes.Length; w++)
                        {
                            data.Columns.Add(new DataColumn(Headings[w], ColumnTypes[w]));
                        }

                        if (addConsts != null)
                        {
                            foreach (ApsimConstant constant in Constants)
                            {
                                if (addConsts.Contains(constant.Name, StringComparer.OrdinalIgnoreCase) && data.Columns.IndexOf(constant.Name) == -1)
                                {
                                    Type ColumnType = StringUtilities.DetermineType(constant.Value, "");
                                    data.Columns.Add(new DataColumn(constant.Name, ColumnType));
                                    addedConstants.Add(new ApsimConstant(constant.Name, constant.Value, constant.Units, ColumnType.ToString()));
                                }
                            }
                        }
                    }

                    DataRow  newMetRow = data.NewRow();
                    object[] values    = ConvertWordsToObjects(words, ColumnTypes);
                    for (int w = 0; w != words.Count; w++)
                    {
                        int TableColumnNumber = newMetRow.Table.Columns.IndexOf(Headings[w]);
                        if (!Convert.IsDBNull(values[TableColumnNumber]))
                        {
                            newMetRow[TableColumnNumber] = values[TableColumnNumber];
                        }
                    }

                    foreach (ApsimConstant constant in addedConstants)
                    {
                        if (constant.Comment == typeof(Single).ToString() || constant.Comment == typeof(Double).ToString())
                        {
                            newMetRow[constant.Name] = Double.Parse(constant.Value);
                        }
                        else
                        {
                            newMetRow[constant.Name] = constant.Value;
                        }
                    }
                    data.Rows.Add(newMetRow);
                    checkHeadingsExist = false;
                }
            }
            return(data);
        }