// // (C) Copyright 2003-2019 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections.Generic; using System.Data; using System.Data.OleDb; using System.IO; namespace Revit.SDK.Samples.RoomSchedule { /// /// An integrated class to connect .xls data source, retrieve / update data /// class XlsDBConnector : IDisposable { #region Class Memeber Variables // The connection created private System.Data.OleDb.OleDbConnection m_objConn; // One command for this connection private OleDbCommand m_command; // The connection string private String m_connectStr; // All available tables(work sheets) in xls data source private List m_tables = new List(); #endregion #region Class Constructor & Destructor /// /// Class constructor, to retrieve data from .xls data source /// /// The .xls file to be connected. /// This file should exist and it can be writable. public XlsDBConnector(String strXlsFile) { // Validate the specified if (!ValidateFile(strXlsFile)) { throw new ArgumentException("The specified file doesn't exists or has readonly attribute.", strXlsFile); } // establish a connection to the data source. m_connectStr = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = \"" + strXlsFile + "\"; Extended Properties = \"Excel 8.0;HDR=YES;\""; // create the .xls connection m_objConn = new System.Data.OleDb.OleDbConnection(m_connectStr); m_objConn.Open(); } /// /// Close the OleDb connection /// public void Dispose() { if (null != m_objConn) { // close the OleDbConnection m_objConn.Close(); m_objConn = null; GC.SuppressFinalize(this); } } /// /// Finalizer, we need to ensure the connection was closed /// This destructor will run only if the Dispose method does not get called. /// ~XlsDBConnector() { Dispose(); } #endregion #region Class Member Methods /// /// Get all available table names from .xls data source /// public List RetrieveAllTables() { // clear the old tables list firstly m_tables.Clear(); // get all table names from data source DataTable schemaTable = m_objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); for (int i = 0; i < schemaTable.Rows.Count; i++) { m_tables.Add(schemaTable.Rows[i].ItemArray[2].ToString().TrimEnd('$')); } return m_tables; } /// /// Generate a DataTable data from xls data source, by a specified table name /// /// Table name to be retrieved /// The generated DataTable from work sheet public DataTable GenDataTable(String tableName) { // Get all data via command and then fill data to table string strCom = "Select * From [" + tableName + "$]"; OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, m_objConn); DataSet myDataSet = new DataSet(); myCommand.Fill(myDataSet, "[" + tableName + "$]"); try { // check to see whether the constant columns(defined in RoomsData class) exist in spread sheet. // These columns are necessary when updating spread sheet // define a flag variable to remember whether column is found // duplicate column is not allowed in spreadsheet bool[] bHasColumn = new bool[5]; Array.Clear(bHasColumn, 0, 5); // clear the variable to false // five constant columns which must exist and to be checked String[] constantNames = { RoomsData.RoomID, RoomsData.RoomName, RoomsData.RoomNumber, RoomsData.RoomArea, RoomsData.RoomComments }; // remember all duplicate columns, used to pop up error message String duplicateColumns = String.Empty; for (int i = 0; i < myDataSet.Tables[0].Columns.Count; i++) { // get each column and check it String columnName = myDataSet.Tables[0].Columns[i].ColumnName; // check whether there are expected columns one by one for (int col = 0; col < bHasColumn.Length; col++) { bool bDupliate = CheckSameColName(columnName, constantNames[col]); if (bDupliate) { if (false == bHasColumn[col]) { bHasColumn[col] = true; } else { // this column is duplicate, reserve it duplicateColumns += String.Format("[{0}], ", constantNames[col]); } } } } // check to see whether there are duplicate columns if (duplicateColumns.Length > 0) { // duplicate columns are not allowed String message = String.Format("There are duplicate column(s) in the spread sheet: {0}.", duplicateColumns); throw new Exception(message); } // check whether all required columns are there. String missingColumns = String.Empty; // reserve all column names which are missing. for (int col = 0; col < bHasColumn.Length; col++) { if (bHasColumn[col] == false) { missingColumns += String.Format("[{0}], ", constantNames[col]); } } // check to see whether any required columns are missing. if (missingColumns.Length != 0) { // some columns are missing, pop up these column names String message = String.Format("Required columns are missing: {0}.", missingColumns); throw new Exception(message); } // if no exception occurs, return the table of dataset directly return myDataSet.Tables[0]; } catch (Exception ex) { // throw exception throw new Exception(ex.Message); } } /// /// Execute SQL command, such as: update and insert /// /// command to be executed /// the number of rows affected by this command public int ExecuteCommnand(String strCmd) { try { if (null == m_command) { m_command = m_objConn.CreateCommand(); } m_command.CommandText = strCmd; return m_command.ExecuteNonQuery(); } catch (Exception ex) { throw new Exception(ex.ToString() + strCmd); } } #endregion #region Class Implementation /// /// This method will validate and update attributes the specified file. /// The file should exist and it should have writable attribute. /// If it's readonly, this method will try to set the attribute to writable. /// /// /// private bool ValidateFile(String strFile) { // exists check if(!File.Exists(strFile)) { return false; } // // writable attribute set File.SetAttributes(strFile, FileAttributes.Normal); return (FileAttributes.Normal == File.GetAttributes(strFile)); } /// /// Check if two columns names are the same /// /// first name /// second name /// true, the two names are same; false, they are different. private static bool CheckSameColName(String baseName, String compName) { if (String.Compare(baseName, compName) == 0) { return true; } else { return false; } } #endregion }; }