Common Tasks

Common Tasks

This guide provides recipes for common operations with the Eriksson Beam API.

Batch Processing Multiple Files

Process multiple beam project files in sequence:

using System;
using System.IO;
using System.Threading.Tasks;
using ErikssonBeam.API.BeamClient;

public class BatchProcessor
{
    private readonly string _licenseKey;
    private readonly string _executablePath;

    public BatchProcessor(string licenseKey, string executablePath)
    {
        _licenseKey = licenseKey;
        _executablePath = executablePath;
    }

    public async Task ProcessDirectory(string directory, Action<BeamDesign> modifier)
    {
        var files = Directory.GetFiles(directory, "*.ebf");
        Console.WriteLine($"Found {files.Length} files to process");

        // Process in batches of 5
        const int batchSize = 5;

        for (int i = 0; i < files.Length; i += batchSize)
        {
            var batch = files.Skip(i).Take(batchSize).ToArray();

            var args = new ErikssonBeamLauncherArgs
            {
                LicenseKey = _licenseKey,
                ExecutablePath = _executablePath,
                FilesToOpen = batch,
                CloseErikssonBeamOnClientDisconnect = true
            };

            using var launcher = await ErikssonBeamLauncher.LaunchErikssonBeam(args);
            var client = launcher.Client;

            foreach (var file in batch)
            {
                var fileName = Path.GetFileNameWithoutExtension(file);
                Console.WriteLine($"  Processing: {fileName}");

                try
                {
                    var design = await client.PullBeamDesignerAsync(fileName);
                    modifier(design);
                    await client.PushBeamDesignerAsync(fileName, design);
                    await client.SaveProject(fileName, file, overwriteExistingFile: true);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"    Error: {ex.Message}");
                }
            }
        }

        Console.WriteLine("Batch processing complete");
    }
}

// Usage
var processor = new BatchProcessor(licenseKey, executablePath);
await processor.ProcessDirectory(@"C:\Projects", design =>
{
    design.DesignCriteria.ProjectInformation.Date = DateTime.Now;
    design.DesignCriteria.ProjectInformation.DesignerName = "Batch Update";
});

Update Project Information Across Files

Standardize project metadata:

public async Task UpdateProjectInfo(
    ErikssonBeamClient client,
    string project,
    string clientName,
    string designerName)
{
    var design = await client.PullBeamDesignerAsync(project);

    var info = design.DesignCriteria.ProjectInformation;
    info.ClientName = clientName;
    info.DesignerName = designerName;
    info.Date = DateTime.Now;

    await client.PushBeamDesignerAsync(project, design);
}

Change Section Type

Convert between section types:

public async Task ConvertToIBeam(ErikssonBeamClient client, string project)
{
    var design = await client.PullBeamDesignerAsync(project);

    // Get length from current section
    double length = 240;  // default
    if (design.ConcreteExtents is TBeam tBeam)
    {
        length = tBeam.Length;
    }
    else if (design.ConcreteExtents is Rectangular rect)
    {
        length = rect.Length;
    }

    // Create new I-Beam section
    design.ConcreteExtents = new IBeam
    {
        Length = length,
        Height = 36,
        TopFlangeWidth = 24,
        BottomFlangeWidth = 24,
        TopFlangeThickness = 6,
        BottomFlangeThickness = 8,
        WebWidth = 6
    };

    await client.PushBeamDesignerAsync(project, design);
}

Add Loads Programmatically

Add distributed loads to multiple projects:

public async Task AddSuperimposedDeadLoad(
    ErikssonBeamClient client,
    string project,
    double loadMagnitude)
{
    var design = await client.PullBeamDesignerAsync(project);

    // Get beam length from section
    double length = 240;
    switch (design.ConcreteExtents)
    {
        case TBeam t: length = t.Length; break;
        case IBeam i: length = i.Length; break;
        case Rectangular r: length = r.Length; break;
    }

    // Add uniform distributed dead load
    design.StructuralModel.Loading.DistributedLoads.Add(new DistributedLoad
    {
        StartLocation = 0,
        EndLocation = length,
        StartMagnitude = loadMagnitude,
        EndMagnitude = loadMagnitude,
        LoadType = LoadType.Dead,
        Description = "Superimposed Dead Load"
    });

    await client.PushBeamDesignerAsync(project, design);
}

Export Design Summary

Extract key information from designs:

public class DesignSummary
{
    public string ProjectName { get; set; }
    public string SectionType { get; set; }
    public double Length { get; set; }
    public int StrandCount { get; set; }
    public double ConcreteStrength { get; set; }
}

public async Task<DesignSummary> ExtractSummary(ErikssonBeamClient client, string project)
{
    var design = await client.PullBeamDesignerAsync(project);

    var summary = new DesignSummary
    {
        ProjectName = design.DesignCriteria.ProjectInformation.ProjectName,
        SectionType = design.ConcreteExtents?.GetType().Name ?? "None",
        ConcreteStrength = design.DesignCriteria.MaterialProperties.Concrete.fc
    };

    // Get length
    switch (design.ConcreteExtents)
    {
        case TBeam t: summary.Length = t.Length; break;
        case IBeam i: summary.Length = i.Length; break;
        case Rectangular r: summary.Length = r.Length; break;
    }

    // Count strands
    summary.StrandCount = design.Reinforcement.Prestress.StrandGroups?
        .Sum(g => g.NumberOfStrands) ?? 0;

    return summary;
}

// Export multiple projects to CSV
public async Task ExportSummariesToCsv(ErikssonBeamClient client, string outputPath)
{
    var projects = await client.GetOpenBeamProjects();

    using var writer = new StreamWriter(outputPath);
    writer.WriteLine("Project,Section,Length,Strands,fc");

    foreach (var project in projects)
    {
        var summary = await ExtractSummary(client, project);
        writer.WriteLine($"{summary.ProjectName},{summary.SectionType},{summary.Length},{summary.StrandCount},{summary.ConcreteStrength}");
    }
}

Connect to User’s Session

Connect to Eriksson Beam the user has open:

public async Task<ErikssonBeamClient> ConnectToUserSession(string licenseKey)
{
    var args = new ErikssonBeamConnectionAttemptArgs
    {
        LicenseKey = licenseKey,
        MaxAttempts = 5,
        WaitTimeBetweenAttemptsMs = 2000
    };

    try
    {
        var client = await ErikssonBeamFinder.GetFirstSupportedBeamClient(args);
        Console.WriteLine("Connected to Eriksson Beam");
        return client;
    }
    catch (ErikssonBeamNotRunningException)
    {
        Console.WriteLine("Eriksson Beam is not running.");
        Console.WriteLine("Please start Eriksson Beam and open your project.");
        return null;
    }
}

Create Template Projects

Create standardized template files:

public async Task CreateTemplateProject(
    string templatePath,
    string projectName,
    string sectionType)
{
    var args = new ErikssonBeamLauncherArgs
    {
        LicenseKey = licenseKey,
        ExecutablePath = executablePath,
        FilesToOpen = Array.Empty<string>(),
        CloseErikssonBeamOnClientDisconnect = true
    };

    using var launcher = await ErikssonBeamLauncher.LaunchErikssonBeam(args);
    var client = launcher.Client;

    // Create blank project
    await client.CreateProjects(new[] { templatePath }, failIfFileExists: false);

    // Open and configure
    // Note: Would need to relaunch to open the new file
    // This is a limitation - use FileManager for this scenario
}

Validate Design Data

Check design for common issues:

public class ValidationResult
{
    public bool IsValid { get; set; }
    public List<string> Errors { get; set; } = new List<string>();
    public List<string> Warnings { get; set; } = new List<string>();
}

public ValidationResult ValidateDesign(BeamDesign design)
{
    var result = new ValidationResult { IsValid = true };

    // Check section
    if (design.ConcreteExtents == null)
    {
        result.Errors.Add("No section defined");
        result.IsValid = false;
    }

    // Check project info
    if (string.IsNullOrEmpty(design.DesignCriteria.ProjectInformation.ProjectName))
    {
        result.Warnings.Add("Project name is empty");
    }

    // Check concrete strength
    var fc = design.DesignCriteria.MaterialProperties.Concrete.fc;
    if (fc < 3000)
    {
        result.Warnings.Add($"Low concrete strength: {fc} psi");
    }
    if (fc > 12000)
    {
        result.Warnings.Add($"Very high concrete strength: {fc} psi");
    }

    // Check prestressing
    var strandCount = design.Reinforcement.Prestress.StrandGroups?
        .Sum(g => g.NumberOfStrands) ?? 0;
    if (strandCount == 0)
    {
        result.Warnings.Add("No prestressing strands defined");
    }

    return result;
}

Monitor Long-Running Operations

Show progress for batch operations:

public async Task ProcessWithProgress(
    string[] files,
    IProgress<(int current, int total, string file)> progress)
{
    int total = files.Length;

    for (int i = 0; i < files.Length; i++)
    {
        var file = files[i];
        progress.Report((i + 1, total, Path.GetFileName(file)));

        // Process file...
        await Task.Delay(100);  // Simulated work
    }
}

// Usage with console progress
var progress = new Progress<(int current, int total, string file)>(p =>
{
    Console.WriteLine($"[{p.current}/{p.total}] Processing: {p.file}");
});

await ProcessWithProgress(files, progress);

See Also