【问题标题】:List down column headers and get the maximum length of string per column列出列标题并获取每列字符串的最大长度
【发布时间】:2017-10-26 14:05:17
【问题描述】:

我正在寻找以 Powershell、vbscript 或 Excel VBA 中的脚本形式翻译我的 Excel 公式。我正在尝试获取列标题列表及其下字符串的最大长度。

通常,我所做的是在 Excel 中手动打开 .txt 文件,从那里我可以获得标题名称。接下来,我创建一个数组公式 =MAX(LEN(A1:A100,000)) 例如。这将获得列中字符串的最大长度。我将对其他列执行相同的公式。

现在我无法执行此操作,因为文件的大小已增加到 1GB,我无法再打开它们,我的桌面崩溃了。也可能是因为 Excel 无法处理超过 100 万行。我的朋友建议使用 Powershell,但我对那里的了解有限.. 不知道是否可以在 vbscript 或 Excel VBA 中完成。

提前感谢您的帮助。

以下代码适用于 .csv 文件,但不适用于 .txt 分隔文件 -

$fileName = "C:\Desktop\EFile.csv"
<#
Sample format of c:\temp\data.csv
"id","name","grade","address"
"1","John","Grade-9","test1"
"2","Ben","Grade-9","test12222"
"3","Cathy","Grade-9","test134343"
#>
$colCount = (Import-Csv  $fileName | Get-Member | Where-Object {$_.MemberType -eq 'NoteProperty'} | Measure-Object).Count
$csv = Import-Csv $fileName 
$csvHeaders = ($csv | Get-Member -MemberType NoteProperty).name

$dict = @{}
foreach($header in $csvHeaders) {
    $dict.Add($header,0)
    }

foreach($row in $csv)
{
    foreach($header in $csvHeaders) 
    {
        if($dict[$header] -le ($row.$header).Length) 
        {
            $dict[$header] =($row.$header).Length
        }
    }
}
$dict.Keys | % { "key = $_ , Column Length = " + $dict.Item($_) }

【问题讨论】:

  • 您尝试过什么,您尝试过什么失败了?理想情况下,您应该提供一个Minimal, Complete, and Verifiable Example 来说明您的尝试,并包含有关它如何失败的具体信息,以及错误消息和/或错误输出。 SO 不是代码编写服务;最好的问题是那些提供有用信息的问题,以便回答的人可以指导您设计自己的正确答案。见How to Ask a Good Question
  • 谢谢。我编辑了我的帖子,我之前是在 Excel 中完成的。我在其中打开 .txt 文件,获取标题名称并插入公式。但是我不能再这样做了,因为 Excel 崩溃了,可能是由于超过 100 万行记录。我的桌面最终崩溃了。
  • 请将您的代码缩减为能够说明您的问题的最小示例,并在此处发布代码。当我们有您正在使用的确切代码时,我们很乐意为您提供帮助,而不必问几十个问题。
  • 嗨,更新了帖子。那是他在 .csv 文件上使用的脚本,但它与 .txt 分隔文件的运行方式不同。他不知道在 .txt 分隔的版本中该做什么。
  • "csv" 代表逗号分隔值,没有“.txt 分隔”标准 - 您需要 Import-Csv $filename -Delimiter "`t" 但使用任何分隔符 - 制表符、管道、空格等。

标签: excel powershell vbscript vba


【解决方案1】:

这就是我获取数据的方式。

$data = @"
"id","name","grade","address"
"1","John","Grade-9","test1"
"2","Ben","Grade-9","test12222"
"3","Cathy","Grade-9","test134343"
"@
$csv = ConvertFrom-Csv -Delimiter ',' $data

但是你应该像这样得到你的数据

$fileName = "C:\Desktop\EFile.csv"
$csv = Import-Csv -Path $fileName

然后

# Extract the header names
$headers = $csv | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name

# Capture output in $result variable
$result = foreach($header in $headers) {

    #                 Select all items in $header column,     find the longest,         and select the item for output
    $maximum = $csv | Select-Object -ExpandProperty $header | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum

    # Generate new object holding the information. 
    # This will end up in $results
    [pscustomobject]@{
        Header = $header
        Max = $maximum.Length
        String = $maximum
    }
}


# Simple output
$result | Format-Table

这是我得到的:

Header  Max String    
------  --- ------    
address  10 test134343
grade     7 Grade-9   
id        1 3         
name      4 John      

或者,如果您在处理大文件时遇到内存问题,您可能不得不对 .NET 框架进行一些处理。这个 sn-p 一次处理一个 csv 行,而不是将整个文件读入内存。

$fileName = "$env:TEMP\test.csv"
$delimiter = ','

# Open a StreamReader
$reader = [System.IO.File]::OpenText($fileName)

# Read the headers and turn it into an array, and trim away any quotes
$headers = $reader.ReadLine() -split $delimiter | % { $_.Trim('"''') }

# Prepare a hashtable for the results
$result = @{}

# So long as there's more data, keep running
while(-not $reader.EndOfStream) {

    # Read a single line and process it as csv
    $csv = $reader.ReadLine() | ConvertFrom-Csv -Header $headers -Delimiter $delimiter

    # Determine if the item in the result hashtable is smaller than the current, using the header as a key
    foreach($header in $headers) {
        $item = $csv | Select-Object -ExpandProperty $header

        if($result[$header].Maximum -lt $item.Length) {
            $result[$header] = [pscustomobject]@{
                Header = $header
                Maximum = $item.Length
                String = $item
            }
        }
    }
}

# Clean up our spent resource
$reader.Close()

# Simple output
$result.Values | Format-Table

【讨论】:

  • Measure-Object -Maximum 在字符串列上通过字母数字比较获取最大字符串,而不是最大长度。它在您的示例中有效,但这只是因为两者相同。如果您添加了另一个字符串,例如“z”,它将显示为最大值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多