Search code examples
c#apirevit-apirevit

Revit API - No Space Tags family is loaded in the project


How can I add Space Tags family using only API? I'm trying use

doc.Create.NewSpaces2(level, phase, view);

(https://www.revitapidocs.com/2019/94b4e479-2301-2e78-6201-5bb5614ed796.htm)

in my project, but I'm getting error "No Space Tags family is loaded in the project".
When I added Annotations/Mechanical/Space Tag.rfa using Revit GUI everything is working.


Solution

  • You could embed the SpaceTag.rfa in your DLL as a resource, and then load it into Revit file programmatically when one is not present.

    Here's an example:

    1. Check if Family exists:

    var loadedFam = new FilteredElementCollector(Doc)
                    .OfClass(typeof(Family))
                    .Cast<Family>()
                    .FirstOrDefault(x.Name == famName);
    

    2. Load the Family if it doesn't exist:

    if (loadedFam == null)
    {
        var resourcePath = GetFamilyFromResource(famName);
        if (string.IsNullOrWhiteSpace(resourcePath) ||
            !e.Document.LoadFamilySymbol(resourcePath,symbolName, out fs)) return null;
    }
    

    3. My utility methods here are:

    private static string GetFamilyFromResource(string resourceName)
        {
            var contents = Resources.StreamBinaryEmbeddedResource(AppCommand.AppInstance.Assembly,
                $"FullPathToResource.{resourceName}.rfa");
            if (!contents.Any()) return string.Empty;
    
            var filePath = Path.Combine(Path.GetTempPath(), $"{resourceName}.rfa");
    
            using (var fileStream = File.Open(filePath, FileMode.Create))
            using (var writer = new BinaryWriter(fileStream))
            {
                writer.Write(contents);
            }
    
            if (!File.Exists(filePath) || new FileInfo(filePath).Length <= 0) return string.Empty;
    
            return filePath;
        }
    
            public static byte[] StreamBinaryEmbeddedResource(Assembly assembly, string fileName)
            {
                using (var stream = assembly.GetManifestResourceStream(fileName))
                {
                    if (stream == null) return new byte[] { };
    
                    var buffer = new byte[stream.Length];
                    stream.Read(buffer, 0, (int)stream.Length);
                    stream.Dispose();
                    return buffer;
                }
            }