VBA按行读取csv文件与分割合并

'2017年2月1日05:43:35 '16年想开发的最后一个Excel代码经过漫长的酝酿与研究终于编写完毕,解决了超过一百万行的csv文件Excel打不开的问题,自动分割为多个sheet,并且数字超过15位不会后面全是0。 '也可以用于平常打开csv文件,速度比直接打开快一倍,还可以用于指定行数分割,多文件合并,csv批量转Excel。 ' '顺道普及:csv文件就是用逗号分隔的数据表,有回车或逗号的文本还有长数字用两个"包围(连续两个表示"本身) 'xlsx文件大小约csv的50%,打开时间约csv的30%,xlsx压缩可能变大,csv压缩后不到10%。

Sub csv分割合并() selectfiles = Application.GetOpenFilename("," & ".", , "打开", , True) '选择文件 If TypeName(selectfiles) = "Boolean" Then '若未选择则结束程序运行 Exit Sub End If

关闭功能
st = Time

spt = [A5]
Ln = [B5]
If spt = "" Then spt = ","
If Not (Ln > 0) Then Ln = 1048576 '用Not是为了包括非数值

Workbooks.Add
li = 2

For Each fp In selectfiles
    
    Set FileObj = CreateObject("Scripting.FileSystemObject")
    Set TextObj = FileObj.OpenTextFile(fp) '定义对象,不耗时
    
    If Not TextObj.AtEndOfLine Then '记录并写入第一个标题行
        TitleText = Split(TextObj.Readline, spt)
        [A1].Resize(1, UBound(TitleText)) = TitleText '在合并工作表时也只是替代第一行
    End If
    
    Do While Not TextObj.AtEndOfLine
        If li > Ln Then '达到一定值新建表
            Sheets.Add
            [A1].Resize(1, UBound(TitleText)) = TitleText
            li = 2
        End If
        Text = Split(TextObj.Readline, spt) '读取行并分割
        Cells(li, 1).Resize(1, UBound(Text)) = Text '测试15位以上数值会保留
        '用时:UBound()<变量<数字,用数组给区域赋值比循环快五六倍左右
        '原先有数值会增加一倍时间,跟直接打开相等
        li = li + 1
    Loop
Next
Debug.Print (Time - st) * 24 * 60 * 60
开启功能

End Sub

Sub csv转xlsx() selectfiles = Application.GetOpenFilename("," & ".", , "打开", , True) '选择文件 If TypeName(selectfiles) = "Boolean" Then '若未选择则结束程序运行 Exit Sub End If

关闭功能
st = Time

spt = [A5]
Ln = 1048576
If spt = "" Then spt = ","
If Not (Ln > 0) Then Ln = 1048576 '用Not是为了包括非数值

For Each fp In selectfiles
    
    Set FileObj = CreateObject("Scripting.FileSystemObject")
    Set TextObj = FileObj.OpenTextFile(fp) '定义对象,不耗时
    
    Workbooks.Add
    li = 2
    
    If Not TextObj.AtEndOfLine Then '记录并写入第一个标题行
        TitleText = Split(TextObj.Readline, spt)
        [A1].Resize(1, UBound(TitleText)) = TitleText '在合并工作表时也只是替代第一行
    End If
    
    Do While Not TextObj.AtEndOfLine
        If li > Ln Then '达到一定值新建表
            Sheets.Add
            [A1].Resize(1, UBound(TitleText)) = TitleText
            li = 2
        End If
        Text = Split(TextObj.Readline, spt) '读取行并分割
        Cells(li, 1).Resize(1, UBound(Text)) = Text '测试15位以上数值会保留
        '用时:UBound()<变量<数字,用数组给区域赋值比循环快五六倍左右
        '原先有数值会增加一倍时间,跟直接打开相等
        li = li + 1
    Loop
    Debug.Print (Time - st) * 24 * 60 * 60
    ActiveWorkbook.SaveAs Left(fp, InStrRev(fp, ".") - 1) & ".xlsx" '保存需要一倍的时间
    ActiveWorkbook.Close 0
Next
Debug.Print (Time - st) * 24 * 60 * 60
开启功能

End Sub

Function 文件打开计时器() selectfiles = Application.GetOpenFilename("," & ".", , "打开", , True) '选择文件 If TypeName(selectfiles) = "Boolean" Then '若未选择则结束程序运行 Exit Function End If 关闭功能 st = Time

For i = 1 To UBound(selectfiles)
Set wb = Workbooks.Open(selectfiles(i))
wb.Close 0 '不保存关闭约1.4e-11s可忽略不计
Next

Debug.Print (Time - st) * 24 * 60 * 60
开启功能

End Function

Sub 关闭功能() '关闭一些功能加快 VBA 宏的运行速度 ' On Error Resume Next '出错继续运行 ' Application.DisplayAlerts = False '禁用警告信息 ' Application.DisplayAlerts = True '启用警告信息 Application.ScreenUpdating = False '禁用屏幕更新 Application.DisplayStatusBar = False '禁用状态栏 Application.Calculation = xlCalculationManual '切换到手动计算-4135,如果中途需要计算时用Calculate Application.EnableEvents = False '禁用事件 ActiveSheet.DisplayPageBreaks = False '禁用本表分页符 End Sub

Sub 开启功能() '开启关闭的功能,调试中断可运行开启功能 Application.ScreenUpdating = True '启用屏幕更新 Application.DisplayStatusBar = True '启用状态栏 Application.Calculation = xlCalculationAutomatic '切换到自动计算-4105 Application.EnableEvents = True '启用事件 'ActiveSheet.DisplayPageBreaks = displayPageBreaksState '启用本表分页符 End Sub

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

通用的序列号生成器库

正如文章《通用的业务编号规则设计实现(附源码)》 文章里需要一个多实例和线程安全的序列化生成器,在SQL Server 2012+ 版本 有一个通过.NET程序...

1685
来自专栏刘望舒

设计模式(十五)状态模式

前言 建议在阅读本文前先阅读设计模式(十一)策略模式这篇文章,虽说状态模式和策略模式的结构几乎是相同的,但是它们所解决的问题是不同的,读完这两篇文章你就会有了答...

1836
来自专栏SDNLAB

OVS中Action源码分析&自定义Action

前言 在生产或是科研中,OpenFlow定义的Action有时候并不能完全满足需求,那么如何向OVS中添加一个自定义的action,本文对此做详细分析。 我们知...

3909
来自专栏Java成神之路

【转】零基础写Java知乎爬虫之进阶篇

说到爬虫,使用Java本身自带的URLConnection可以实现一些基本的抓取页面的功能,但是对于一些比较高级的功能,比如重定向的处理,HTML标记的去除,仅...

903
来自专栏枕边书

搭建自己的PHP框架心得(二)

续言 对于本次更新,我想说: 本框架由本人挑时间完善,而我还不是PHP大神级的人物,所以框架漏洞难免,求大神们指出。 本框架的知识点应用都会写在博客里,大家有什...

1718
来自专栏刘望舒

Android内存优化(五)详解内存分析工具MAT

前言 在这个系列的前四篇文章中,我分别介绍了DVM、ART、内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT。 ...

2898
来自专栏林德熙的博客

win10 uwp 验证输入 自定义用户控件 Nuget使用库判断输入字符长度是否要检查长度判断如何写检查用户控件

TextBox是给用户输入,我们有时要用户只输入数字,而用户输入汉字,我们就有提示用户,那么这东西用到次数很多,我们需要做成一个控件。 我们可以用别人的库,我找...

633
来自专栏一“技”之长

Xcode中修改变量名、类名及字符串的替换操作

        在做iOS开发代码优化的工作时,优化代码结构之前,我们应该先整理好工程的外貌,将文件和类的命名进行规范,在Xcode中为我们提供了方便而强大的名...

592
来自专栏对角另一面

lodash源码分析之List缓存

昨日我沿着河岸/漫步到/芦苇弯腰喝水的地方 顺便请烟囱/在天空为我写一封长长的信 潦是潦草了些/而我的心意/则明亮亦如你窗前的烛光/稍有暧昧之处/势所难免...

2606
来自专栏刘君君

Validator 使用总结

1896

扫码关注云+社区