Example #1
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication app = commandData.Application;
            Document      doc = app.ActiveUIDocument.Document;
            bool          rc;

            using (Transaction t = new Transaction(doc))
            {
                #region 3.2.a Load an entire RFA family file:

                // Load a whole Family
                //
                // Example for a family WITH TXT file:

                rc = doc.LoadFamily(LabConstants.WholeFamilyFileToLoad1);
                #endregion // 3.2.a

                if (rc)
                {
                    LabUtils.InfoMsg("Successfully loaded family "
                                     + LabConstants.WholeFamilyFileToLoad1 + ".");
                }
                else
                {
                    LabUtils.ErrorMsg("ERROR loading family "
                                      + LabConstants.WholeFamilyFileToLoad1 + ".");
                }

                // Example for a family WITHOUT TXT file:

                rc = doc.LoadFamily(LabConstants.WholeFamilyFileToLoad2);

                if (rc)
                {
                    LabUtils.InfoMsg("Successfully loaded family "
                                     + LabConstants.WholeFamilyFileToLoad2 + ".");
                }
                else
                {
                    LabUtils.ErrorMsg("ERROR loading family "
                                      + LabConstants.WholeFamilyFileToLoad2 + ".");
                }

                #region 3.2.b Load an individual type from a RFA family file:

                // Load only a specific symbol (type):

                rc = doc.LoadFamilySymbol(
                    LabConstants.FamilyFileToLoadSingleSymbol,
                    LabConstants.SymbolName);
                #endregion // 3.2.b

                if (rc)
                {
                    LabUtils.InfoMsg("Successfully loaded family symbol "
                                     + LabConstants.FamilyFileToLoadSingleSymbol + " : "
                                     + LabConstants.SymbolName + ".");
                }
                else
                {
                    LabUtils.ErrorMsg("ERROR loading family symbol "
                                      + LabConstants.FamilyFileToLoadSingleSymbol + " : "
                                      + LabConstants.SymbolName + ".");
                }
                t.Commit();
            }
            return(Result.Succeeded);
        }
Example #2
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication app   = commandData.Application;
            UIDocument    uidoc = app.ActiveUIDocument;
            Document      doc   = uidoc.Document;

            FamilyInstance inst =
                LabUtils.GetSingleSelectedElementOrPrompt(
                    uidoc, typeof(FamilyInstance))
                as FamilyInstance;

            if (null == inst)
            {
                LabUtils.ErrorMsg(
                    "Selected element is not a "
                    + "standard family instance.");

                return(Result.Cancelled);
            }

            // determine selected instance category:

            Category instCat = inst.Category;

            Dictionary <string, List <FamilySymbol> >
            mapFamilyToSymbols
                = new Dictionary <string, List <FamilySymbol> >();

            {
                WaitCursor waitCursor = new WaitCursor();

                // Collect all types applicable to this category and sort them into
                // a dictionary mapping the family name to a list of its types.
                //
                // We create a collection of all loaded families for this category
                // and for each one, the list of all loaded types (symbols).
                //
                // There are many ways how to store the matching objects, but we choose
                // whatever is most suitable for the relevant UI. We could use Revit's
                // generic Map class, but it is probably more efficient to use the .NET
                // strongly-typed Dictionary with
                // KEY = Family name (String)
                // VALUE = list of corresponding FamilySymbol objects
                //
                // find all corresponding families and types:

                FilteredElementCollector families
                    = new FilteredElementCollector(doc);

                families.OfClass(typeof(Family));

                foreach (Family f in families)
                {
                    bool categoryMatches = false;

                    ISet <ElementId> ids = f.GetFamilySymbolIds(); // 2015

                    // we cannot trust f.Category or
                    // f.FamilyCategory, so grab the category
                    // from first family symbol instead:

                    //foreach( FamilySymbol sym in f.Symbols ) // 2014

                    foreach (ElementId id in ids) // 2015
                    {
                        Element symbol = doc.GetElement(id);

                        categoryMatches = symbol.Category.Id.Equals(
                            instCat.Id);

                        break;
                    }

                    if (categoryMatches)
                    {
                        List <FamilySymbol> symbols
                            = new List <FamilySymbol>();

                        //foreach( FamilySymbol sym in f.Symbols ) // 2014
                        foreach (ElementId id in ids) // 2015
                        {
                            FamilySymbol symbol = doc.GetElement(id) as FamilySymbol;

                            symbols.Add(symbol);
                        }

                        mapFamilyToSymbols.Add(f.Name, symbols);
                    }
                }
            }

            // display the form allowing the user to select
            // a family and a type, and assign this type
            // to the instance.

            Lab3_4_Form form
                = new Lab3_4_Form(mapFamilyToSymbols);

            if (System.Windows.Forms.DialogResult.OK
                == form.ShowDialog())
            {
                using (Transaction t = new Transaction(doc))
                {
                    t.Start("Change Selected Instance Type");
                    inst.Symbol = form.cmbType.SelectedItem
                                  as FamilySymbol;
                    t.Commit();
                }

                LabUtils.InfoMsg(
                    "Successfully changed family : type to "
                    + form.cmbFamily.Text + " : "
                    + form.cmbType.Text);
            }
            return(Result.Succeeded);
        }
Example #3
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication app   = commandData.Application;
            UIDocument    uidoc = app.ActiveUIDocument;
            Document      doc   = uidoc.Document;

            //ElementSet ss = uidoc.Selection.Elements; // 2014
            ICollection <ElementId> ids = uidoc.Selection.GetElementIds();

            Wall wall = null;

            if (0 < ids.Count)
            {
                // old pre-selection handling:

                // must be one single element only:

                if (1 != ids.Count)
                {
                    message = "Please pre-select a single wall element.";
                    return(Result.Failed);
                }

                // must be a wall:

                //ElementSetIterator it = ss.ForwardIterator();
                //it.MoveNext();
                //Element e = it.Current as Element;

                ElementId id = ids.First <ElementId>();
                Element   e  = doc.GetElement(id);

                if (!(e is Wall))
                {
                    message = "Selected element is NOT a wall.";
                    return(Result.Failed);
                }
                wall = e as Wall;
            }
            else
            {
                // new prompt for filtered selection allowing only walls:

                try
                {
                    Reference r = uidoc.Selection.PickObject(
                        ObjectType.Element, new WallSelectionFilter(),
                        "Please pick a wall");

                    //wall = r.Element as Wall; // 2011
                    wall = uidoc.Document.GetElement(r) as Wall; // 2012
                }
                catch (OperationCanceledException)
                {
                    message = "Selection cancelled.";
                    return(Result.Cancelled);
                }
            }

            // wall must be constrained to a level at the top (more on parameters later):

            Level topLev = null;

            try
            {
                ElementId id = wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
                topLev = doc.GetElement(id) as Level;
            }
            catch (Exception)
            {
                topLev = null;
            }

            if (null == topLev)
            {
                message = "Selected wall is not constrained to a level at the top.";
                return(Result.Failed);
            }

            // get the bottom level as well (this should never fail):

            Level botLev = null;

            try
            {
                ElementId id = wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).AsElementId();
                botLev = doc.GetElement(id) as Level;
            }
            catch (Exception)
            {
                botLev = null;
            }

            if (null == botLev)
            {
                message = "Selected wall is not constrained to a level at the bottom.";
                return(Result.Failed);
            }

            // Calculate the location points for the 3 columns (assuming straight wall)
            LocationCurve locCurve = wall.Location as LocationCurve;

            XYZ ptStart = locCurve.Curve.GetEndPoint(0);
            XYZ ptEnd   = locCurve.Curve.GetEndPoint(1);
            XYZ ptMid   = 0.5 * (ptStart + ptEnd);

            List <XYZ> locations = new List <XYZ>(3);

            locations.Add(ptStart);
            locations.Add(ptMid);
            locations.Add(ptEnd);

            string        s = "{0} location{1} for the new columns in raw database coordinates, e.g. feet{2}";
            List <string> a = new List <string>();

            a.Add("Start: " + LabUtils.PointString(ptStart));
            a.Add("Mid  : " + LabUtils.PointString(ptMid));
            a.Add("End  : " + LabUtils.PointString(ptEnd));
            LabUtils.InfoMsg(s, a);

            FilteredElementCollector collector = new FilteredElementCollector(doc);

            collector.OfCategory(BuiltInCategory.OST_Columns);
            collector.OfClass(typeof(FamilySymbol));

#if SEARCH_FOR_SPECIFIC_NAME
            // retrieve the family type for the new instances.
            // if needed, change the names to match a column
            // type available in the model:

            string family_name = "M_Wood Timber Column";
            string type_name   = "191 x 292mm";

            // LINQ query to find element with given name:
            //
            // ... note that this could also be achieved by
            // filtering for the element name parameter value.

            var column_types = from element in collector
                               //where ((FamilySymbol)element).Family.Name == family_name
                               where element.Name == type_name
                               select element;

            FamilySymbol symbol = null;

            try
            {
                symbol = column_types.Cast <FamilySymbol>().First <FamilySymbol>();
            }
            catch
            {
            }

            if (null == symbol)
            {
                message = string.Format(
                    "Cannot find type '{0}' in family '{1}' in the current model - please load it first.",
                    type_name, family_name);
                return(Result.Failed);
            }
#endif // SEARCH_FOR_SPECIFIC_NAME

            FamilySymbol symbol = collector.Cast <FamilySymbol>().First <FamilySymbol>();

            if (null == symbol)
            {
                message = "Cannot find a suitable column type.";
                return(Result.Failed);
            }

            using (Transaction tx = new Transaction(doc))
            {
                tx.Start("Insert Columns and Move Wall");

                // insert column family instances:

                foreach (XYZ p in locations)
                {
                    try
                    {
                        // Note: Currently there is a problem.
                        // If we set the type as NonStructural, it is treated as Annotation instance,
                        // and it shows only in plan view.
                        // FamilyInstance column = doc.Create.NewFamilyInstance( p, symbol, botLev, StructuralType.NonStuctural );

                        FamilyInstance column = doc.Create.NewFamilyInstance(
                            p, symbol, botLev, StructuralType.Column);

                        Parameter paramTopLevel = column.get_Parameter(
                            BuiltInParameter.FAMILY_TOP_LEVEL_PARAM);

                        ElementId id = topLev.Id;

                        paramTopLevel.Set(id);
                    }
                    catch (Exception)
                    {
                        LabUtils.ErrorMsg("Failed to create or adjust column.");
                    }
                }

                // Finally, move the wall so the columns are visible.
                // We move the wall perpendicularly to its location
                // curve by one tenth of its length:

                XYZ v = new XYZ(
                    -0.1 * (ptEnd.Y - ptStart.Y),
                    0.1 * (ptEnd.X - ptStart.X),
                    0);

                if (!wall.Location.Move(v))
                {
                    LabUtils.ErrorMsg("Failed to move the wall.");
                }
                tx.Commit();
            }
            return(Result.Succeeded);
        }
Example #4
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            #region 2.1.a. Access Revit doc and open output file:
            UIApplication app = commandData.Application;
            Document      doc = app.ActiveUIDocument.Document;

            // .NET exception handling should be done everywhere,
            // but will sometimes be omitted for clarity in the
            // following labs unless we expect exceptions:

            StreamWriter sw;

            try
            {
                sw = new StreamWriter(LabConstants.FilePath);
            }
            catch (Exception e)
            {
                LabUtils.ErrorMsg(string.Format("Cannot open '{0}': {1}",
                                                LabConstants.FilePath, e.Message));
                return(Result.Failed);
            }
            #endregion // 2.1.a. Access Revit doc and open output file

            try
            {
                WaitCursor waitCursor = new WaitCursor();

                #region 2.1.b. Set up element collector to retrieve all elements:
                // the Revit API does not expect an application
                // ever to need to iterate over all elements.
                // To do so, we need to use a trick: ask for all
                // elements fulfilling a specific criteria and
                // unite them with all elements NOT fulfilling
                // the same criteria:

                FilteredElementCollector collector
                    = new FilteredElementCollector(doc)
                      .WhereElementIsElementType();

                FilteredElementCollector collector2
                    = new FilteredElementCollector(doc)
                      .WhereElementIsNotElementType();

                collector.UnionWith(collector2);
                #endregion // 2.1.b. Set up element collector to retrieve all elements

                #region 2.1.c. Loop over the elements, list their data, and close the file:
                string s, line;

                foreach (Element e in collector)
                {
                    line  = "Id=" + e.Id.IntegerValue.ToString(); // element id
                    line += "; Class=" + e.GetType().Name;        // element class, i.e. System.Type

                    // The element category is not implemented for all classes,
                    // and may return null; for Family elements, one can sometimes
                    // use the FamilyCategory property instead.

                    s = string.Empty;

                    if (null != e.Category)
                    {
                        s = e.Category.Name;
                    }
                    if (0 == s.Length && e is Family && null != ((Family)e).FamilyCategory)
                    {
                        s = ((Family)e).FamilyCategory.Name;
                    }
                    if (0 == s.Length)
                    {
                        s = "?";
                    }
                    line += "; Category=" + s;

                    // The element Name has a different meaning for different classes,
                    // but is mostly implemented "logically". More precise info on elements
                    // can be obtained in class-specific ways.

                    line += "; Name=" + e.Name;
                    line += "; UniqueId=" + e.UniqueId;
                    //line += "; Guid=" + GetGuid( e.UniqueId );
                    sw.WriteLine(line);
                }
                sw.Close();

                LabUtils.InfoMsg("Element list has been written to "
                                 + LabConstants.FilePath + ".");

                #endregion // 2.1.c. Loop over the elements, list their data, and close the output file
            }
            catch (Exception e)
            {
                message = e.Message;
            }
            return(Result.Failed);
        }
Example #5
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            Application   app   = uiapp.Application;
            Document      doc   = uiapp.ActiveUIDocument.Document;

            //BindingMap bindingMap = doc.ParameterBindings; // slow, fixed in 2009 wu 3, cf. case 1247995

            Guid paramGuid = LabUtils.SharedParamGUID(app,
                                                      LabConstants.SharedParamsGroupAPI, LabConstants.SharedParamsDefFireRating);

            // Let user select the Excel file.

            WinForms.OpenFileDialog dlg = new WinForms.OpenFileDialog();
            dlg.Title  = "Select source Excel file from which to update Revit shared parameters";
            dlg.Filter = "Excel spreadsheet files (*.xls;*.xlsx)|*.xls;*.xlsx|All files (*)|*";
            if (WinForms.DialogResult.OK != dlg.ShowDialog())
            {
                return(Result.Cancelled);
            }

            // Launch/Get Excel via COM Interop:

            X.Application excel = new X.Application();
            if (null == excel)
            {
                LabUtils.ErrorMsg("Failed to get or start Excel.");
                return(Result.Failed);
            }
            excel.Visible = true;
            X.Workbook workbook = excel.Workbooks.Open(dlg.FileName,
                                                       Missing.Value, Missing.Value, Missing.Value,
                                                       Missing.Value, Missing.Value, Missing.Value, Missing.Value,
                                                       Missing.Value, Missing.Value, Missing.Value, Missing.Value,
                                                       Missing.Value, Missing.Value, Missing.Value);
            X.Worksheet worksheet = workbook.ActiveSheet as X.Worksheet;

            using (Transaction t = new Transaction(doc))
            {
                t.Start("Import Fire Rating Values from Excel");

                // Starting from row 2, loop the rows and extract Id and FireRating param.

                int    id;
                double fireRatingValue;
                int    row = 2;
                while (true)
                {
                    try
                    {
                        // Extract relevant XLS values.

                        X.Range r = worksheet.Cells[row, 1] as X.Range;
                        if (null == r.Value2)
                        {
                            break;
                        }
                        double d = (double)r.Value2;
                        id = (int)d;
                        if (0 >= id)
                        {
                            break;
                        }
                        r = worksheet.Cells[row, 4] as X.Range;
                        fireRatingValue = (double)r.Value2;

                        // Get document's door element via Id

                        ElementId elementId = new ElementId(id);
                        Element   door      = doc.GetElement(elementId);

                        // Set the param

                        if (null != door)
                        {
                            //Parameter parameter = door.get_Parameter( LabConstants.SharedParamsDefFireRating );
                            Parameter parameter = door.get_Parameter(paramGuid);
                            parameter.Set(fireRatingValue);
                        }
                    }
                    catch (Exception)
                    {
                        break;
                    }
                    ++row;
                }
                t.Commit();
            }

#if ACTIVATE_REVIT
            //
            // Set focus back to Revit (there may be a better way, but this works :-)
            //

#if USE_PROCESS_GET_PROCESSES
            foreach (Process p in Process.GetProcesses())
            {
                try
                {
                    if ("REVIT" == p.ProcessName.ToUpper().Substring(0, 5))
                    {
                        // In VB, we can use AppActivate( p.Id );
                        // Pre-3.0, I think you may need to use p/invoke and call the native Windows
                        // SetForegroundWindow() function directly.
                        // http://www.codeproject.com/csharp/windowhider.asp?df=100
                        break;
                    }
                }
                catch (Exception)
                {
                }
            }
#endif // USE_PROCESS_GET_PROCESSES

            JtRevitWindow w = new JtRevitWindow();
            w.Activate();
#endif // ACTIVATE_REVIT

            return(Result.Succeeded);
        }
Example #6
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            Application   app   = uiapp.Application;
            Document      doc   = uiapp.ActiveUIDocument.Document;

            Category cat = doc.Settings.Categories.get_Item(
                Lab4_3_1_CreateAndBindSharedParam.Target);

            // Launch Excel (same as in Lab 4_2, so we really
            // should have better created some utils...)

            X.Application excel = new X.ApplicationClass();
            if (null == excel)
            {
                LabUtils.ErrorMsg("Failed to get or start Excel.");
                return(Result.Failed);
            }
            excel.Visible = true;
            X.Workbook  workbook = excel.Workbooks.Add(Missing.Value);
            X.Worksheet worksheet;
            //while( 1 < workbook.Sheets.Count )
            //{
            //  worksheet = workbook.Sheets.get_Item( 0 ) as X.Worksheet;
            //  worksheet.Delete();
            //}
            worksheet             = excel.ActiveSheet as X.Worksheet;
            worksheet.Name        = "Revit " + cat.Name;
            worksheet.Cells[1, 1] = "ID";
            worksheet.Cells[1, 2] = "Level";
            worksheet.Cells[1, 3] = "Tag";
            worksheet.Cells[1, 4] = LabConstants.SharedParamsDefFireRating;
            worksheet.get_Range("A1", "Z1").Font.Bold = true;

            List <Element> elems = LabUtils.GetTargetInstances(doc,
                                                               Lab4_3_1_CreateAndBindSharedParam.Target);

            // Get Shared param Guid

            Guid paramGuid = LabUtils.SharedParamGUID(app,
                                                      LabConstants.SharedParamsGroupAPI,
                                                      LabConstants.SharedParamsDefFireRating);

            if (paramGuid.Equals(Guid.Empty))
            {
                LabUtils.ErrorMsg("No Shared param found in the file - aborting...");
                return(Result.Failed);
            }

            // Loop through all elements and export each to an Excel row

            int row = 2;

            foreach (Element e in elems)
            {
                worksheet.Cells[row, 1] = e.Id.IntegerValue; // ID

                // Level:

                //worksheet.Cells[row, 2] = e.Level.Name; // 2013
                //worksheet.Cells[row, 2] = doc.GetElement( e.LevelId ).Name; // 2014

                // When attaching a shared parameter to Material
                // elements, no valid level is defined, of course:

                ElementId levelId = e.LevelId;
                string    levelName
                    = ElementId.InvalidElementId == levelId
            ? "N/A"
            : doc.GetElement(levelId).Name;
                worksheet.Cells[row, 2] = levelName;

                // Tag:

                Parameter tagParameter = e.get_Parameter(
                    BuiltInParameter.ALL_MODEL_MARK);
                if (null != tagParameter)
                {
                    worksheet.Cells[row, 3] = tagParameter.AsString();
                }

                // FireRating:

                Parameter parameter = e.get_Parameter(paramGuid);
                if (null != parameter)
                {
                    worksheet.Cells[row, 4] = parameter.AsDouble();
                }
                ++row;
            }
            return(Result.Succeeded);
        }
Example #7
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication app = commandData.Application;
            Document      doc = app.ActiveUIDocument.Document;

            // Extract and group the data from Revit in a
            // dictionary, where the key is the category
            // name and the value is a list of elements.

            Stopwatch sw = Stopwatch.StartNew();

            Dictionary <string, List <Element> > sortedElements
                = new Dictionary <string, List <Element> >();

            // Iterate over all elements, both symbols and
            // model elements, and them in the dictionary.

            ElementFilter f = new LogicalOrFilter(
                new ElementIsElementTypeFilter(false),
                new ElementIsElementTypeFilter(true));

            FilteredElementCollector collector
                = new FilteredElementCollector(doc)
                  .WherePasses(f);

            string name;

            foreach (Element e in collector)
            {
                Category category = e.Category;

                if (null != category)
                {
                    name = category.Name;

                    // If this category was not yet encountered,
                    // add it and create a new container for its
                    // elements.

                    if (!sortedElements.ContainsKey(name))
                    {
                        sortedElements.Add(name,
                                           new List <Element>());
                    }
                    sortedElements[name].Add(e);
                }
            }

            // Launch or access Excel via COM Interop:

            X.Application excel = new X.Application();

            if (null == excel)
            {
                LabUtils.ErrorMsg(
                    "Failed to get or start Excel.");

                return(Result.Failed);
            }
            excel.Visible = true;

            X.Workbook workbook = excel.Workbooks.Add(
                Missing.Value);

            X.Worksheet worksheet;

            // We cannot delete all work sheets,
            // Excel requires at least one.
            //
            //while( 1 < workbook.Sheets.Count )
            //{
            //  worksheet = workbook.Sheets.get_Item(1) as X.Worksheet;
            //  worksheet.Delete();
            //}

            // Loop through all collected categories and
            // create a worksheet for each except the first.
            // We sort the categories and work trough them
            // from the end, since the worksheet added last
            // shows up first in the Excel tab.

            List <string> keys = new List <string>(
                sortedElements.Keys);

            keys.Sort();
            keys.Reverse();

            bool first = true;

            int nElements   = 0;
            int nCategories = keys.Count;

            foreach (string categoryName in keys)
            {
                List <Element> elementSet
                    = sortedElements[categoryName];

                // Create and name the worksheet

                if (first)
                {
                    worksheet = workbook.Sheets.get_Item(1)
                                as X.Worksheet;

                    first = false;
                }
                else
                {
                    worksheet = excel.Worksheets.Add(
                        Missing.Value, Missing.Value,
                        Missing.Value, Missing.Value)
                                as X.Worksheet;
                }

                name = (31 < categoryName.Length)
          ? categoryName.Substring(0, 31)
          : categoryName;

                name = name
                       .Replace(':', '_')
                       .Replace('/', '_');

                worksheet.Name = name;

                // Determine the names of all parameters
                // defined for the elements in this set.

                List <string> paramNames = new List <string>();

                foreach (Element e in elementSet)
                {
                    ParameterSet parameters = e.Parameters;

                    foreach (Parameter parameter in parameters)
                    {
                        name = parameter.Definition.Name;

                        if (!paramNames.Contains(name))
                        {
                            paramNames.Add(name);
                        }
                    }
                }
                paramNames.Sort();

                // Add the header row in bold.

                worksheet.Cells[1, 1] = "ID";
                worksheet.Cells[1, 2] = "IsType";

                int column = 3;

                foreach (string paramName in paramNames)
                {
                    worksheet.Cells[1, column] = paramName;
                    ++column;
                }
                var range = worksheet.get_Range("A1", "Z1");

                range.Font.Bold = true;
                range.EntireColumn.AutoFit();

                int row = 2;

                foreach (Element e in elementSet)
                {
                    // First column is the element id,
                    // second a flag indicating type (symbol)
                    // or not, both displayed as an integer.

                    worksheet.Cells[row, 1] = e.Id.IntegerValue;

                    worksheet.Cells[row, 2] = (e is ElementType)
            ? 1
            : 0;

                    column = 3;

                    string paramValue;

                    foreach (string paramName in paramNames)
                    {
                        paramValue = "*NA*";

                        //Parameter p = e.get_Parameter( paramName ); // 2014

                        // Careful! This returns the first best param found.

                        Parameter p = e.LookupParameter(paramName); // 2015

                        if (null != p)
                        {
                            //try
                            //{
                            paramValue
                                = LabUtils.GetParameterValue(p);
                            //}
                            //catch( Exception ex )
                            //{
                            //  Debug.Print( ex.Message );
                            //}
                        }

                        worksheet.Cells[row, column++]
                            = paramValue;
                    } // column

                    ++nElements;
                    ++row;
                } // row
            }     // category == worksheet


            sw.Stop();

            TaskDialog.Show("Parameter Export",
                            string.Format(
                                "{0} categories and a total "
                                + "of {1} elements exported "
                                + "in {2:F2} seconds.",
                                nCategories, nElements,
                                sw.Elapsed.TotalSeconds));

            return(Result.Succeeded);
        }