2011-09-28 71 views
0

使用电子表格工具,是否有任何方法可以获得列的“可能”数据类型,不包括标题行(如果存在)以及合理容忍稀疏人口而不必自己做一个样本...有没有办法做到这一点?不包括标题行的Excel列数据类型

因此,例如,如果我有一个excel行像

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

我希望看到

字符串,字符串,日期时间,字符串,数字

编辑

所以我最终不得不像@Tim Anderson所建议的那样进行采样,但我需要处理稀疏数据的情况,并且默认t o当col中的类型冲突时的字符串。 (这是在一个遍历cols的循环中调用的,我不能发布它,因为它包含一些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; 
     } 
    } 
} 

我相信这可以进一步改善,所以请随时发布改进,但这是我现在需要的。

回答

1

任何辅助方法,或其他API中的SpreadsheetGear存在自动返回“可能的数据类型”为一列值的所有转换功能概括这一点。实现这样的事情并不会很困难,以满足您自己的特定需求,但如果不对数据进行“抽样”,则无法做到这一点。下面是一个非常简单的方法,它接受要检查的范围和一个指示范围是否包含标题行的布尔值。它所做的只是检查第一行数据以确定类型;你可能需要构建一些更健壮:

你应该知道的
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时(这些包括空,错误,逻辑,数字,文本)。请注意,没有DateTime。在您的示例中,这会影响“销售日期”列中返回的值类型,因为日期/时间实际上是作为表示日期/时间序列号的双精度存储在Excel和SpreadsheetGear中的。所以这种类型的值将返回Number,而不是像DateTime。它们在单元格中显示为“日期”的事实仅仅是单元格的NumberFormat函数。

+0

谢谢@Tim Anderson。事实上,我最终做了类似的事情,尽管我还需要对一些行进行抽样以处理稀疏数据。如果有人需要做类似的事情,我会编辑我的文章。 –

1

在从不使用的SpreadsheetGear,但在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 

我相信这是可能适应

的[]

+0

感谢您回复@布鲁诺,但没有这不是我所需要的。在电子表格设备中,实际值本身(range.Value)似乎总是一个字符串,但存在该范围的ValueType属性,但这总是只给出该范围中左上角单元格的类型,即使该范围是“ EntireColumn“,这意味着使用这种机制,我将不得不进行抽样以获得”可能“类型。我希望有一些辅助方法或类已经这样做。 –

0

这里是另一个尝试基于错误处理程序和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(see this link on ozgrid