Тип данных столбца Excel, исключая строку заголовка - PullRequest
0 голосов
/ 29 сентября 2011

Используя SpreadSheetgear, есть ли способ получить «вероятный» тип данных для столбца, исключая строку заголовка (если она существует) и достаточно терпимую к разреженной популяции без необходимости делать выборку самому ...уже способ сделать это?

так, например, если бы у меня была строка Excel, такая как

| Customers | Sales Item | Sale Date  | Contact | Quantity |
| IBM       | Keyboard   | 28-10-2011 |         | 2        |
| MS        | Mouse      | 27-09-2011 | joe     | 5        |

, я бы ожидал увидеть

String, String, DateTime, String, Numeric

РЕДАКТИРОВАТЬ

Таким образом, я закончил с выборкой, как предложил @Tim Anderson, но мне нужно было обработать случай разреженных данных и установить значение по умолчанию для строки при конфликте типов в столбце.(это вызывается в цикле, который обходит столбцы, я не могу опубликовать его, так как он содержит некоторый IP-адрес). DataValueType - это просто локальное перечисление, а rowcount - это количество строк для выборки, а поскольку я уже выполняю выборку, я просто игнорирую строку 0.в случае, если это строка заголовка.

private DataType GetDataTypeFromColRange(IRange range, int rowcount, int col)
{
    var dtlist = GetValueTypes(range, rowcount, col).Distinct();
    // If conflicting types for the col default to string.
    if (dtlist.Count() != 1)
    {
        return new DataType(DataTypeValue.String);
    }
    else
    {
        return new DataType(dtlist.First());
    }
}

private IEnumerable<DataTypeValue> GetValueTypes(IRange range, int rowcount, int col)
{
    for (int i = 1; i < rowcount; i++)
    {
        switch (range[i, col].ValueType)
        {
            case SpreadsheetGear.ValueType.Text:
                yield return DataTypeValue.String;
                break;
            case SpreadsheetGear.ValueType.Number:
                if (range[i, col].NumberFormatType == NumberFormatType.Date || range[i, col].NumberFormatType ==  NumberFormatType.DateTime)
                {
                    yield return DataTypeValue.Date;
                }
                else
                {
                    yield return DataTypeValue.Numeric;
                }
                break;
            case SpreadsheetGear.ValueType.Logical:
                yield return DataTypeValue.Bool;
                break;
            default: // ignore empty or errored cells.
                continue;
        }
    }
}

Я уверен, что это можно еще улучшить, поэтому, пожалуйста, не стесняйтесь публиковать улучшения, но это делает то, что мне сейчас нужно.

Ответы [ 3 ]

1 голос
/ 30 сентября 2011

В SpreadsheetGear не существует вспомогательного метода или другого API для автоматического возврата «вероятного типа данных» для столбца значений. Было бы не очень сложно реализовать что-то подобное для удовлетворения ваших собственных конкретных требований, хотя без «выборки» данных сделать это невозможно. Ниже приведен очень простой метод, который принимает проверяемый диапазон, и логическое значение, указывающее, содержит ли диапазон строку заголовка. Все, что он делает, это проверяет первую строку данных, чтобы определить тип; Возможно, вы захотите создать что-то более надежное:

private SpreadsheetGear.ValueType[] GetColumnTypes(IRange range, bool hasHeader)
{
    SpreadsheetGear.ValueType[] columnTypes = new SpreadsheetGear.ValueType[range.ColumnCount];
    for (int i = 0; i < range.ColumnCount; i++)
    {
        columnTypes[i] = range[hasHeader ? 1 : 0, i].ValueType;
    }
    return columnTypes;
}

Однако следует помнить, что SpreadsheetGear использует те же базовые внутренние типы данных, что и Excel, и возвращает эти типы при проверке IRange.ValueType (к ним относятся «Пусто», «Ошибка», «Логический», «Число», «Текст»). Обратите внимание, что нет даты и времени. В вашем примере это повлияет на тип значения, возвращаемый в столбце «Дата продажи», поскольку даты и время фактически хранятся в Excel и SpreadsheetGear в виде двойных чисел, представляющих серийный номер даты / времени. Таким образом, этот тип значения будет возвращать Number, а не что-то вроде DateTime. Тот факт, что они отображаются как «дата» в ячейке, является просто функцией NumberFormat ячейки.

1 голос
/ 29 сентября 2011

В никогда не использовать электронные таблицы, но в Excel я использую этот UDF

Function GetType(rg As Range) As String

If IsNumeric(rg.Value) Then
    GetType = "Numeric"
ElseIf IsDate(rg.Value) Then
    GetType = "Date Time"
Else
    GetType = "String"
End If

End Function

Я считаю, что можно адаптировать

[] 's

0 голосов
/ 29 сентября 2011

Вот еще одна попытка, основанная на обработчике ошибок и преобразовании типов VBA:

Function probableType(vInput As Variant)
Dim vResult As Variant

'set error handler to resume (the procedure will check the error number)
On Error Resume Next

'check if it is an integer
vResult = CInt(vInput)
If Err.Number = 0 Then
    probableType = "Integer"
    Exit Function
End If
Err.Clear

'check if it is a date
vResult = CDate(vInput)
If Err.Number = 0 Then
    probableType = "Date"
    Exit Function
End If
Err.Clear

'else this is probably a string
probableType = "String"
End Function

Можно проверить с помощью этого подпрограммы:

Sub uniTest()
MsgBox probableType("12/12/12")
MsgBox probableType("12")
MsgBox probableType("myTest")
End Sub

Вы можете обобщить это со всеми функциями преобразованияExcel VBA ( см. эту ссылку на ozgrid )

...