public FhirSpreadsheet(string filename, DataSet ds)
        {
            // **** set fields from parameters ****

            Filename      = filename;
            LoadedDataSet = ds;

            // **** ****

            KnownTabs   = new HashSet <string>();
            UnknownTabs = new HashSet <string>();
            IgnoredTabs = new HashSet <string>();

            // **** traverse all the tabs ****

            foreach (DataTable dt in ds.Tables)
            {
                if (string.IsNullOrEmpty(dt.TableName))
                {
                    continue;
                }

                if (_ignoredTabs.Contains(dt.TableName))
                {
                    IgnoredTabs.Add(dt.TableName);
                    continue;
                }

                // **** act depending on name ****

                switch (dt.TableName)
                {
                case "Bindings":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Data Elements":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Events":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Examples":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Extensions":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Instructions":
                    UnknownTabs.Add(dt.TableName);
                    break;

                case "Invariants":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Metadata":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Operations":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Profiles":
                    KnownTabs.Add(dt.TableName);
                    break;

                case "Search":
                    KnownTabs.Add(dt.TableName);
                    break;

                default:

                    // **** check for invariants tab ****

                    if ((dt.TableName.EndsWith("-Inv")) &&
                        (TabInvariants.TableIsCompatible(dt)))
                    {
                        // **** test for invariants tab ****

                        KnownTabs.Add(dt.TableName);
                    }
                    else if ((dt.TableName.EndsWith("-search")) &&
                             (TabSearch.TableIsCompatible(dt)))
                    {
                        // **** test for search tab ****

                        KnownTabs.Add(dt.TableName);
                    }
                    else if ((char.IsLower(dt.TableName[0])) &&
                             (TabCodeList.TableIsCompatible(dt)))
                    {
                        // **** test for code list tab ***

                        KnownTabs.Add(dt.TableName);
                    }
                    else if ((char.IsUpper(dt.TableName[0])) &&
                             (TabProfiles.TableIsCompatible(dt)))
                    {
                        // **** test for profile tab ****

                        KnownTabs.Add(dt.TableName);
                    }
                    else
                    {
                        UnknownTabs.Add(dt.TableName);
                    }

                    break;
                }
            }

            // **** tell the user what's going on ****

            DumpTabs();
        }