如何在Excel表上运行SQL查询?


81

我正在尝试从所有按姓氏排序的姓氏字段的另一个表中创建一个子表,该表的电话号码字段不为空。我可以使用SQL轻松做到这一点,但是我不知道如何在Excel中运行SQL查询。我很想将数据导入postgresql并在那里查询,但这似乎有点多余。

对于我想做的事情,SQL查询SELECT lastname, firstname, phonenumber WHERE phonenumber IS NOT NULL ORDER BY lastname可以解决问题。对于Excel本身无法做到的事情来说,看起来太简单了。如何在Excel中运行这样的SQL查询?


您要在SQL本身还是在应用程序内部执行此操作?
约翰·宾厄姆

2
我已对此进行了彻底调查,并在exceldevelopmentplatform.blogspot.com/2018/10/…上
S

Answers:


69

有很多很好的方法可以做到这一点,其他人已经建议过。遵循“通过SQL轨道获取Excel数据”,下面是一些指针。

  1. Excel具有“数据连接向导”,它使您可以从另一个数据源甚至在同一Excel文件中导入或链接。

  2. 作为Microsoft Office(和OS)的一部分,有两个感兴趣的提供程序:旧的“ Microsoft.Jet.OLEDB”和最新的“ Microsoft.ACE.OLEDB”。设置连接时(例如使用数据连接向导)查找它们。

  3. 一旦连接到Excel工作簿,工作表或范围就等同于表格或视图。工作表的表名称是在工作表的名称后附加一个美元符号(“ $”),并用方括号(“ [”和“]”)括起来;范围的名称,只是该范围的名称。要将未命名的单元格范围指定为记录源,请在方括号中的工作表名称末尾附加标准Excel行/列符号。

  4. 本机SQL将(或多或少是)Microsoft Access的SQL。(在过去,它被称为JET SQL;但是Access SQL已经发展了,我相信JET已经过时了。)

  5. 例如,阅读工作表: SELECT * FROM [Sheet1$]

  6. 例如,读取范围: SELECT * FROM MyRange

  7. 例如,读取一个未命名的单元格范围: SELECT * FROM [Sheet1$A1:B10]

  8. 有许多许多书籍和网站可用来帮助您完成所有细节。

===其他说明===

默认情况下,假定Excel数据源的第一行包含可用作字段名称的列标题。如果不是这种情况,则必须关闭此设置,否则第一行数据“消失”以用作字段名称。这是通过HDR= setting在连接字符串的扩展属性中添加可选项来完成的。无需指定的默认值为HDR=Yes。如果没有列标题,则需要指定HDR=No;。提供商将您的字段命名为F1,F2等。

有关指定工作表的警告:提供程序假定您的数据表以指定工作表上最上方,最左侧,非空白的单元格开头。换句话说,您的数据表可以毫无问题地从第3行C列开始。但是,例如,您不能在单元格A1中数据的左上方和左上方输入workheeet标题。

关于指定范围的警告:当您将工作表指定为记录源时,提供程序会在空间允许的情况下在工作表中现有记录的下方添加新记录。当您指定范围(命名或未命名)时,Jet还会在空间允许的情况下在该范围内的现有记录下方添加新记录。但是,如果您在原始范围上重新查询,则结果记录集将不包括该范围之外的新添加的记录。

C的数据类型(值得尝试)REATE TABLE: Short, Long, Single, Double, Currency, DateTime, Bit, Byte, GUID, BigBinary, LongBinary, VarBinary, LongText, VarChar, Decimal

连接到“老技术” Excel文件(文件与XLS extention) Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\MyFolder\MyWorkbook.xls;Extended Properties=Excel 8.0;。将Excel 5.0源数据库类型用于Microsoft Excel 5.0和7.0(95)工作簿,并将Excel 8.0源数据库类型用于Microsoft Excel 8.0(97),9.0(2000)和10.0(2002)工作簿。

连接到“最新” Excel(具有xlsx文件扩展名的文件): Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Excel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;"

将数据视为文本:IMEX设置将所有数据视为文本。 Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Excel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;IMEX=1";

(有关更多详细信息,请访问http://www.connectionstrings.com/excel

有关更多信息,请参见http://msdn.microsoft.com/zh-CN/library/ms141683(v=sql.90).aspxhttp://support.microsoft.com/kb/316934

通过VBA通过ADODB连接到Excel的详细信息,网址http://support.microsoft.com/kb/257819

有关Microsoft JET 4的详细信息,请访问http://support.microsoft.com/kb/275561


4
数据连接需要一个文件名,当任务要查询当前文件时,该文件名将成为显示停止符。此外,查询不能像公式一样使用,只能使用固定查询来填充范围;并且不会自动更新。因此,无法查询当前文件,也不能用作公式的直接替代。
ivan_pozdeev '18年

2
@ivan_pozdeev我刚刚使用Excel 2010确认可以查询当前文件。我不知道更高版本的Excel / Office是否使这不再可能。我同意通过“数据连接向导”创建自引用表很麻烦-很大程度上是因为使用工作簿的完整路径建立了连接,因此重命名/复制/移动工作簿会导致破坏它或使结果混乱。但是,对于使用VBA并不是问题的工作簿,自引用查询非常易于管理。
rskar

@ivan_pozdeev我也同意Excel没有针对自动刷新自引用表进行优化;该推定始终是外部来源的数据。可以通过“连接属性”的“用法”选项卡进行自动刷新(就像每隔这么多分钟后重新加载一样),并且使用VBA可以利用重新计算事件。不过,我不相信我会以超低的价格替代公式。
rskar,

2
“有很多好的方法可以完成此任务” –如果这不能掩盖所有这些“好的”方法在请求的用例中实际上存在的主要缺陷(这防止其广泛使用的原因),我不知道这是什么。
ivan_pozdeev '18年

8

tl; dr; Excel本机执行所有这些操作-使用过滤器和/或

http://office.microsoft.com/en-gb/excel-help/filter-data-in-an-excel-table-HA102840028.aspx

您可以通过oledb连接以编程方式打开excel,并在工作表中的表上执行SQL。

但是,您可以做所有您想做的事情,而无需公式,只需过滤器即可。

  1. 要查看的数据中单击任意位置
  2. 转到功能区栏上的数据
  3. 选择“过滤器”,它大约在中间,看起来像一个漏斗
    • 现在,表格第一行中每个单元格的紧边上都会有箭头
  4. 单击电话号码上的箭头,然后取消选择空格(最后一个选项)
  5. 单击姓氏上的箭头,然后选择z顺序(顶部选项)

玩一玩..一些注意事项:

  1. 您可以选择过滤的行并将其粘贴到其他位置
  2. 在左侧的状态栏中,您会看到符合条件的行总数中有多少行符合您的过滤条件。(例如,找到313条记录中的308条)
  3. 您可以在病房的excel 2010中按颜色过滤
  4. 有时,我创建计算列以提供状态或数据的干净版本,然后您也可以按这些内容进行过滤或排序。(例如,像其他答案中的公式一样)

除非要进行很多操作或者要自动在某处或某处自动导入数据,否则请使用过滤器执行此操作。但是为了完整性:

一个c#选项:

 OleDbConnection ExcelFile = new OleDbConnection( String.Format( "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR=YES\"", filename));
 ExcelFile.Open();

一个方便的起点是看一下架构,因为那里可能比您想象的要多:

List<String> excelSheets = new List<string>();

// Add the sheet name to the string array.
foreach (DataRow row in dt.Rows) {
    string temp = row["TABLE_NAME"].ToString();
    if (temp[temp.Length - 1] == '$') {
         excelSheets.Add(row["TABLE_NAME"].ToString());
    }
}

然后,当您要查询工作表时:

 OleDbDataAdapter da = new OleDbDataAdapter("select * from [" + sheet + "]", ExcelFile);
 dt = new DataTable();
  da.Fill(dt);

注意-在excel中使用表格!:

Excel具有“表”功能,该功能使数据的行为更像表。.这为您带来了很多好处,但并不能让您进行每种查询。

http://office.microsoft.com/zh-CN/excel-help/overview-of-excel-tables-HA010048546.aspx

对于excel中的表格数据,这是我的默认设置。我要做的第一件事是单击数据,然后从功能区的主页部分中选择“表格格式”。这使您可以进行过滤和默认排序,并允许您按名称访问表和字段(例如table [fieldname]),这还允许在列上聚合函数,例如max和average


如果您想减少列数,我个人会把过滤后的行复制到新的工作表中,然后删除我不需要的列。您可以隐藏它们,但很少值得这么做。

1
using System.Data.OleDb; using System.Data;

1
我每天都进行过滤,而c#每周要访问几次电子表格。当使用c#时,它往往是将数据导入到db中以真正发挥作用。.对于实际查询其过滤器或sql,一旦数据进入sql server则不值得在中间sql到excel级别上做。

7

您可以按如下方式进行本机操作:

  1. 选择表并使用Excel对“姓氏”进行排序
  2. 创建一个2行乘1列的高级过滤器条件,例如在E1和E2中,其中E1为空,E2包含公式=C6="" ,其中C6是电话号码列的第一个数据单元格。
  3. 选择表并使用高级过滤器,使用E1:E2中的条件范围将其复制到一个范围,并指定要将输出复制到的位置

如果要以编程方式执行此操作,建议您使用宏记录器记录上述步骤并查看代码。


8
问题指定SQL。
S Meaden '18年

4

可以在Excel中使用SQL。它只是隐藏得很好。请参阅本教程:

http://smallbusiness.chron.com/use-sql-statements-ms-excel-41193.html


2
看起来好像正在使用SQL选择要导入Excel的数据,但是,是否不针对当前电子表格运行查询?
Rup

您只需要在excel中(在名称管理器中)为每个表创建一个名称,或者只选择表并在显示单元格地址的框中键入名称即可。然后,您可以使用它来查询工作表。在查询中,您具有工作表的完整地址,因此,如果将电子表格移动到磁盘上的其他位置,查询将无法工作
Petrik

3

我建议尝试一下QueryStorm,它是Excel的插件,可以很方便地在Excel中使用SQL。

另外,它是免费的。如果您不关心自动完成,错误提示等,则可以免费使用。只需下载并安装,即可在Excel中获得SQL支持。

免责声明:我是作者。


1
不幸的是,尽管它是一个很棒的工具,但它现在似乎只是付费的,除了30天的试用期。
马克

2

如果您需要一次执行此操作,则只需遵循Charles的描述,但也可以使用Excel公式和帮助程序列进行此操作,以防您使过滤器动态化。

假设您的数据在工作表DataSheet上,并从以下几列的第2行开始:

  • 答:姓氏
  • B:名字
  • C:电话号码

在此工作表上需要两个帮助器列。

  • D2:,=if(A2 = "", 1, 0)这是过滤器列,与您的where条件相对应
  • E2:,=if(D2 <> 1, "", sumifs(D$2:D$1048576, A$2:A$1048576, "<"&A2) + sumifs(D$2:D2, A$2:A2, A2))这对应于

尽可能复制这些公式。

在应显示结果的工作表上,创建以下列。

  • 答:从第2行中的1开始的数字序列,这限制了您可以获得的总行数(有点儿像续集中的限制)
  • B2 :=match(A2, DataSheet!$E$2:$E$1048576, 0),这是对应数据的行
  • C2:,=iferror(index(DataSheet!A$2:A$1048576, $B2), "")这是实际数据;如果不存在数据,则为空

将B2和C2中的公式复制下来,并将列C复制到D和E。


-1

您可以使用您选择的语言/平台试用Excel的本机数据库驱动程序。在Java世界中,您可以尝试使用http://code.google.com/p/sqlsheet/,它提供了一个JDBC驱动程序,可直接使用Excel工作表。同样,您可以获取其他平台的数据库技术驱动程序。

但是,我可以保证您很快就会了解这些包装器库提供的​​许​​多功能。更好的方法是使用Apache HSSF / POI或类似级别的库,但需要更多的编码工作。


-1

我可能会误解我,但这不是数据透视表的功能吗?您将数据存储在表中还是仅在过滤列表中?如果不是表格,则将其设为一个(ctrl + 1),然后只需激活表格中的任何单元格,然后将数据透视表插入另一张纸上即可。然后将“姓氏,名字,电话号码”列添加到“行”部分。然后将“电话号码”添加到过滤器部分,并过滤出空值。现在按正常排序。



-1

如果您使用Expat库的GDAL / OGR进行了编译,则可以使用XLSX驱动程序读取.xlsx文件,并从命令提示符下运行SQL表达式。例如,从与电子表格相同目录中的osgeo4w shell使用ogrinfo实用程序:

ogrinfo -dialect sqlite -sql "SELECT name, count(*) FROM sheet1 GROUP BY name" Book1.xlsx

会在上运行SQLite查询sheet1,并以不寻常的形式输出查询结果:

INFO: Open of `Book1.xlsx'
      using driver `XLSX' successful.

Layer name: SELECT
Geometry: None
Feature Count: 36
Layer SRS WKT:
(unknown)
name: String (0.0)
count(*): Integer (0.0)
OGRFeature(SELECT):0
  name (String) = Red
  count(*) (Integer) = 849

OGRFeature(SELECT):1
  name (String) = Green
  count(*) (Integer) = 265
...

或使用ogr2ogr运行相同的查询以创建一个简单的CSV文件:

$ ogr2ogr -f CSV out.csv -dialect sqlite \
          -sql "SELECT name, count(*) FROM sheet1 GROUP BY name" Book1.xlsx

$ cat out.csv
name,count(*)
Red,849
Green,265
...

要对较旧的.xls文件执行类似操作,您将需要针对FreeXL库构建的XLS驱动程序,这并不是很常见(例如,不是来自OSGeo4w)。


-2

Microsoft Access和LibreOffice Base可以打开电子表格作为源并在其上运行sql查询。这将是运行各种查询的最简单方法,并且避免了运行宏或编写代码的麻烦。

Excel还具有自动过滤器和数据排序功能,可以完成许多简单的查询,例如您的示例。如果您需要这些功能的帮助,那么Google将是比我更好的教程来源。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.