CSVHelper: используйте IndexAttribute для записи пустых полей - PullRequest
1 голос
/ 06 июня 2019

У нас есть фиксированный формат выходной записи, где все поля разделены каналом.Макет является фиксированным, но обязательные поля расположены не по порядку (и это нельзя изменить, поскольку клиенты используют существующий макет).Можем ли мы использовать CSVHelper и атрибут Index для записи пустых полей, например, [Index (1)], [Index (4)], [Index (7)] даст что-то вроде:

"Field1Value,,,Field2Value,,,Field3Value"?

Мыможет в конечном итоге добавить пропущенные поля, но придется учитывать это поэтапно (из-за последствий для клиента), но мы хотим иметь возможность создать минимальный формат выходной записи с необходимыми значениями полей.

Мыработа с .Net Core 2.2 / C # для наших усилий.

Я просмотрел несколько библиотек nuget и других библиотек, которые поддерживают декорирование свойств с помощью атрибутов данных, таких как [Column (xx)] и [FieldOrder (xx)], но остановились.на CSVHelper, потому что он кажется надежным и широко используемым.

public class Person
{
    [Index(1)]
    public string Name { get; set; }
    [Index(4)]
    public short Age { get; set; }
    [Index(7)]
    public string StreetAddress { get; set; }
}

static void Main(string[] args)
{
    var records = new List<Person>
    {
        new Person { Name = "Jon Doe", Age = 100, StreetAddress = "123 Market Place" }
    };

    using (var writer = new StreamWriter("C:\\Projects\\CsvHelperDemo\\file.csv"))
    using (var csv = new CsvWriter(writer))
    {
        csv.WriteRecords(records);
    }
}

Ожидаемый:

Name,,,Age,,,StreetAddress
Jon Doe,,,100,,,123 Market Place

Фактический:

Name,Age,StreetAddress
Jon Doe,100,123 Market Place

1 Ответ

1 голос
/ 06 июня 2019

Если это вариант, я бы просто добавил свойства в класс Person. Если они не заполнены, то у вас просто будут имена столбцов без данных под ними. Это немного странно, но не сильно отличается от наличия «пустых» имен столбцов и пустых столбцов.

Но если вы хотите получить именно тот результат, который вы описываете, вы можете сделать это:

public class Person
{
    [Index(0)]
    public string Name { get; set; }

    [Index(3)]
    public short Age { get; set; }

    [Index(6)]
    public string StreetAddress { get; set; }

    #region For spacing only

    [Name("")]
    [Index(1)]
    public string Abc { get; set; }

    [Name("")]
    [Index(2)]
    public string Xyz { get; set; }

    [Name("")]
    [Index(4)]
    public string Foo { get; set; }

    [Name("")]
    [Index(5)]
    public string Blarg { get; set; }

    #endregion
}

Я использовал поддельные имена. Вместо этого вы можете использовать настоящие. Это не имеет значения, потому что заголовок столбца будет пустым.

Одним недостатком является то, что вы можете начать заполнять одно из тех дополнительных свойств, которые вы не используете сейчас, и тогда столбец будет заполняться без заголовка, если вы не забудете вернуться назад и удалить атрибут [Name(""}].

Вы также можете создать отдельный унаследованный класс без изменения Person. Таким образом, вы заполняете Person, а затем сопоставляете его с унаследованным классом и используете его для записи:

public class PersonWithExtraFields : Person
{
    [Name("")]
    [Index(1)]
    public string Abc { get; set; }

    [Name("")]
    [Index(2)]
    public string Xyz { get; set; }

    [Name("")]
    [Index(4)]
    public string Foo { get; set; }

    [Name("")]
    [Index(5)]
    public string Blarg { get; set; }
}

Это буквальный ответ, описывающий, как это сделать с помощью CsvHelper. Вот более простой способ:

public class PersonCsvWriter
{
    public void Write(List<Person> people, string path)
    {
        using (var file = new StreamWriter(path))
        {
            file.WriteLine("Name,,,Age,,,StreetAddress");
            people.ForEach(p => file.WriteLine($"{p.Name},,,{p.Age},,,{p.StreetAddress}"));
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...