Oleオートメーション手順を許可できる場合は、このソリューションを次のように使用できます。 @OutputFileNameパラメーターを使用しないストアドプロシージャを作成し、bcpを使用してバイナリコンテンツをファイルに保存することもできます(出力の先頭にデータを追加せずにバイナリコンテンツをエクスポートするフォーマットファイルを使用)。
これは、必要なテキストまたは数値の書式を使用してExcelスプレッドシートを簡単に生成できないことへの不満から書きました。手順AddFileToArchiveは、入力ファイルの内容を含むzipアーカイブを生成し、GetExcelSpreadsheetDataによって内部的に使用されます。
GetExcelSpreadsheetDataは、1つ以上の一時テーブルのワークシートを生成し、準拠したopenxmlワークブックを出力します。ワークシートには太字の列見出しがあります。拡張子が.zipのファイルを出力すると、他の.xlsxファイルと同様の内部ファイルの内容が表示されますが、データは共有値ではなくインラインで内部的に保存されます。 「autofilter」オプションを追加することで、ワークシートを自動フィルタリングできます。
現在、日付の書式設定はdd / mm / yyyyにハードコーディングされていますが、次の行を変更することで変更できます。
<numFmt formatCode="dd/mm/yyyy\ hh:mm" numFmtId="165"/>
<numFmt formatCode="hh:mm" numFmtId="166"/>
<numFmt formatCode="dd/mm/yyyy" numFmtId="167"/>
コメント不足でごめんなさい。
SQL Server CheckSumはCRCを計算しますか?そうでない場合、MS SQLで任意のvarchar列のCRCを計算するにはどうすればよいですか? SQLServer2012または2014で実行された場合に使用されるGetCRC32コードの場合。
下部の使用例。
うまくいけば、これがお役に立てば幸いです。この手順は、SQLServer2008R2以前では機能しません。
/****** Object: UserDefinedFunction [dbo].[GetCRC32] Script Date: 23/10/2020 4:52:31 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create function [dbo].[GetCRC32](@Text varchar(max)) returns binary(4) as
begin
declare
@crc bigint = 0xFFFFFFFF
,@Lookup varbinary(2048) = 0x0000000077073096EE0E612C990951BA076DC419706AF48FE963A5359E6495A30EDB883279DCB8A4E0D5E91E97D2D98809B64C2B7EB17CBDE7B82D0790BF1D911DB710646AB020F2F3B9714884BE41DE1ADAD47D6DDDE4EBF4D4B55183D385C7136C9856646BA8C0FD62F97A8A65C9EC14015C4F63066CD9FA0F3D638D080DF53B6E20C84C69105ED56041E4A26771723C03E4D14B04D447D20D85FDA50AB56B35B5A8FA42B2986CDBBBC9D6ACBCF94032D86CE345DF5C75DCD60DCFABD13D5926D930AC51DE003AC8D75180BFD0611621B4F4B556B3C423CFBA9599B8BDA50F2802B89E5F058808C60CD9B2B10BE9242F6F7C8758684C11C1611DABB6662D3D76DC419001DB710698D220BCEFD5102A71B1858906B6B51F9FBFE4A5E8B8D4337807C9A20F00F9349609A88EE10E98187F6A0DBB086D3D2D91646C97E6635C016B6B51F41C6C6162856530D8F262004E6C0695ED1B01A57B8208F4C1F50FC45765B0D9C612B7E9508BBEB8EAFCB9887C62DD1DDF15DA2D498CD37CF3FBD44C654DB261583AB551CEA3BC0074D4BB30E24ADFA5413DD895D7A4D1C46DD3D6F4FB4369E96A346ED9FCAD678846DA60B8D044042D7333031DE5AA0A4C5FDD0D7CC95005713C270241AABE0B1010C90C20865768B525206F85B3B966D409CE61E49F5EDEF90E29D9C998B0D09822C7D7A8B459B33D172EB40D81B7BD5C3BC0BA6CADEDB883209ABFB3B603B6E20C74B1D29AEAD547399DD277AF04DB261573DC1683E3630B1294643B840D6D6A3E7A6A5AA8E40ECF0B9309FF9D0A00AE277D079EB1F00F93448708A3D21E01F2686906C2FEF762575D806567CB196C36716E6B06E7FED41B7689D32BE010DA7A5A67DD4ACCF9B9DF6F8EBEEFF917B7BE4360B08ED5D6D6A3E8A1D1937E38D8C2C44FDFF252D1BB67F1A6BC57673FB506DD48B2364BD80D2BDAAF0A1B4C36034AF641047A60DF60EFC3A867DF55316E8EEF4669BE79CB61B38CBC66831A256FD2A05268E236CC0C7795BB0B4703220216B95505262FC5BA3BBEB2BD0B282BB45A925CB36A04C2D7FFA7B5D0CF312CD99E8B5BDEAE1D9B64C2B0EC63F226756AA39C026D930A9C0906A9EB0E363F720767850500571395BF4A82E2B87A147BB12BAE0CB61B3892D28E9BE5D5BE0D7CDCEFB70BDBDF2186D3D2D4F1D4E24268DDB3F81FDA836E81BE16CDF6B9265B6FB077E118B7477788085AE6FF0F6A7066063BCA11010B5C8F659EFFF862AE69616BFFD3166CCF45A00AE278D70DD2EE4E0483543903B3C2A7672661D06016F74969474D3E6E77DBAED16A4AD9D65ADC40DF0B6637D83BF0A9BCAE53DEBB9EC547B2CF7F30B5FFE9BDBDF21CCABAC28A53B3933024B4A3A6BAD03605CDD7069354DE572923D967BFB3667A2EC4614AB85D681B022A6F2B94B40BBE37C30C8EA15A05DF1B2D02EF8D
,@LenText int = len(@Text);
with x as (
select '' as Id
union all
select '' as Id from x
)
,y as (select top (cast(ceiling(sqrt(sqrt(@LenText))) as int)) '' as id from x)
,v as (
select top (@LenText) row_number() over (order by (select null)) as ID
from y cross join y as y2 cross join y as y3 cross join y as y4
)
SELECT @crc = (@crc / 256) ^ Substring(@Lookup, ((@crc & 0xFF) ^ Ascii(Substring(@Text, V.ID, 1))) * 4 + 1, 4)
FROM V
SET @crc = [email protected];
return cast(reverse(cast(@crc as varbinary(4))) as binary(4));
end
GO
/****** Object: UserDefinedFunction [dbo].[StringSplit2] Script Date: 23/10/2020 4:52:32 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create function [dbo].[StringSplit2] (@StringToSplit varchar(max), @Seperator char(1)) returns table
as
return (
with Split as (
select
1 as ValueOrder
,cast(1 as int) as ValueStartPos
,cast(charindex(@Seperator, @StringToSplit + @Seperator) as int) as ValueEndPos
union all
select
ValueOrder + 1 as ValueOrder
,ValueEndPos + 1 as ValueStartPos
,cast(charindex(@Seperator, @StringToSplit + @Seperator, ValueEndPos + 1) as int) as ValueEndPos
from Split
where ValueEndPos <> 0
)
select
ValueOrder
,substring(@StringToSplit, ValueStartPos, case when ValueEndPos = 0 then 0 else ValueEndPos-ValueStartPos end) as value
from Split
where ValueEndPos <> 0
)
GO
/****** Object: StoredProcedure [dbo].[AddFileToArchive] Script Date: 23/10/2020 4:52:32 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create procedure [dbo].[AddFileToArchive](@FileName varchar(max), @FileContents varbinary(max), @ArchiveData varbinary(max) output, @ArchiveInfo binary(10) output)
as
begin
set nocount on;
declare
@LocalFileHeaderSignature binary(4) = 0x504b0304
,@CentralDirectoryFileHeaderSignature binary(4) = 0x504b0102
,@EndOfCentralDirectorySignature binary(4) = 0x504b0506
,@VersionNeededToExtract binary(2) = 0x1400
,@VersionMadeBy binary(2) = 0x1400
,@GeneralPurposeBitFlag binary(2) = 0x0000
,@CompressionMethod binary(2) = 0x0000--0x0800
,@CompressionMethodDeflate binary(2) = 0x0800
,@FileLastModificationTime binary(2) = 0xA351 -- dummy time
,@FileLastModificationDate binary(2) = 0x6250 -- dummy date
,@currentDateTime datetime = getdate()
,@CRC32 binary(4)
,@CompressedSize int
,@UncompressedSize int
,@FileNameLength smallint
,@ExtraFieldLength smallint = 0
,@FileCommentLength smallint = 0
,@CommentLength smallint = 0
,@NumberOfThisDisk smallint = 0
,@DiskNumberWhereFileStarts smallint = 0
,@InternalFileAttributes binary(2) = 0x0100
,@ExternalFileAttributes binary(4) = 0x20000000
,@LocalFileRecordLength int
,@LocalFileRecord varbinary(max)
,@CompressedFileContents varbinary(max)
,@LenCompressedFileContents int
,@FileCRC32 binary(4)
,@OffsetOfStartOfCentralDirectory int
,@CentralDirectoryRecord varbinary(max)
,@EndOfCentralDirectoryRecord varbinary(max)
,@sql nvarchar(max)
,@OtherFileCount smallint
,@FileOffset int
,@SizeOfCentralDirectory int;
set @OtherFileCount = IsNull(cast(SubString(@ArchiveInfo, 1, 2) as smallint), 0);
set @FileOffset = IsNull(cast(SubString(@ArchiveInfo, 3, 4) as int), 0);
set @SizeOfCentralDirectory = IsNull(cast(SubString(@ArchiveInfo, 7, 4) as int), 0);
set @FileLastModificationTime = cast(reverse(cast((datepart(ss, @currentDateTime) / 2) | (32 * datepart(mi, @currentDateTime)) | (2048 * datepart(hh, @currentDateTime)) as binary(2))) as binary (2));
set @FileLastModificationDate = cast(reverse(cast((datepart(dd, @currentDateTime)) | (32 * datepart(mm, @currentDateTime)) | (512 * (datepart(yy, @currentDateTime) - 1980)) as binary(2))) as binary (2));
-- for SQL Server 2016 or higher compress the file contents
if cast(serverproperty('ProductMajorVersion') as int) > 12 -- SQL Server 2016+
begin
exec sp_executesql
@stmt = N'set @CompressedFileContents = compress(@FileContents)'
,@params = N'@FileContents varbinary(max), @CompressedFileContents varbinary(max) output'
,@CompressedFileContents = @CompressedFileContents output
,@FileContents = @FileContents;
set @FileCRC32 = substring(@CompressedFileContents, len(@CompressedFileContents) - 7, 4);
set @CompressionMethod = @CompressionMethodDeflate;
end
else
begin
set @CompressedFileContents = 0x00000000000000000000 + @FileContents + 0x0000000000000000;
exec sp_executesql
@stmt = N'set @FileCRC32 = dbo.GetCRC32(@FileContents)'
,@params = N'@FileContents varbinary(max), @FileCRC32 binary(4) output'
,@FileContents = @FileContents
,@FileCRC32 = @FileCRC32 output;
end;
set @LenCompressedFileContents = len(@CompressedFileContents);
set @CompressedSize = @LenCompressedFileContents - 18;
set @UncompressedSize = len(@FileContents);
set @FileNameLength = len(@FileName);
set @LocalFileRecord =
@LocalFileHeaderSignature
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
+cast(reverse(cast(@CompressedSize as binary(4))) as binary(4))
+cast(reverse(cast(@UncompressedSize as binary(4))) as binary(4))
+cast(reverse(cast(@FileNameLength as binary(2))) as binary(2))
+cast(reverse(cast(@ExtraFieldLength as binary(2))) as binary(2))
+cast(@FileName as varbinary(max))
+substring(@CompressedFileContents, 11, @LenCompressedFileContents - 18);
set @CentralDirectoryRecord =
@CentralDirectoryFileHeaderSignature
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
+cast(reverse(cast(@CompressedSize as binary(4))) as binary(4))
+cast(reverse(cast(@UncompressedSize as binary(4))) as binary(4))
+cast(reverse(cast(@FileNameLength as binary(2))) as binary(2))
+cast(reverse(cast(@ExtraFieldLength as binary(2))) as binary(2))
+cast(reverse(cast(@FileCommentLength as binary(2))) as binary(2))
+cast(reverse(cast(@DiskNumberWhereFileStarts as binary(2))) as binary(2))
[email protected]
[email protected]
+cast(reverse(cast(@FileOffset as binary(4))) as binary(4))
+cast(@FileName as varbinary(max));
set @SizeOfCentralDirectory = @SizeOfCentralDirectory + len(@CentralDirectoryRecord);
set @LocalFileRecordLength= len(@LocalFileRecord)
set @OffsetOfStartOfCentralDirectory = @FileOffset + @LocalFileRecordLength;
set @EndOfCentralDirectoryRecord =
@EndOfCentralDirectorySignature
+cast(reverse(cast(@NumberOfThisDisk as binary(2))) as binary(2))
+cast(reverse(cast(@NumberOfThisDisk as binary(2))) as binary(2)) -- Disk where central directory starts
+cast(reverse(cast(@OtherFileCount + cast(1 as smallint) as binary(2))) as binary(2)) -- Number of central directory records on this disk
+cast(reverse(cast(@OtherFileCount + cast(1 as smallint) as binary(2))) as binary(2)) -- Total number of central directory records
+cast(reverse(cast(@SizeOfCentralDirectory as binary(4))) as binary(4))
+cast(reverse(cast(@OffsetOfStartOfCentralDirectory as binary(4))) as binary(4))
+cast(reverse(cast(@CommentLength as binary(2))) as binary(2))
if @ArchiveInfo is null
set @ArchiveData = @LocalFileRecord + @CentralDirectoryRecord + @EndOfCentralDirectoryRecord
else
set @ArchiveData =
SubString(@ArchiveData, 1, @FileOffset) + @LocalFileRecord
+SubString(@ArchiveData, @FileOffset + 1, @SizeOfCentralDirectory - len(@CentralDirectoryRecord)) + @CentralDirectoryRecord
[email protected];
set @ArchiveInfo =
cast(@OtherFileCount + 1 as binary(2))
+ cast(@FileOffset + @LocalFileRecordLength as binary(4))
+ cast(@SizeOfCentralDirectory as binary(4));
-- select @ArchiveInfo as ArchiveInfo, @LocalFileRecord as LocalFileRecord,@CentralDirectoryRecord as CentralDirectoryRecord, @EndOfCentralDirectoryRecord as EndOfCentralDirectoryRecord
return;
end
GO
/****** Object: StoredProcedure [dbo].[GetExcelSpreadsheetData] Script Date: 23/10/2020 4:52:32 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE procedure [dbo].[GetExcelSpreadsheetData](@SheetName varchar(31) = null, @Worksheets varchar(max) = null, @WorkbookData varbinary(max) = null output, @OutputFileName nvarchar(500) = null)
as
set nocount on;
declare
@LocalFileRecords varbinary(max)
,@CentralDirectoryRecords varbinary(max)
,@EndOfCentralDirectoryRecord varbinary(max)
,@OtherFileCount smallint
,@FileOffset int
,@SizeOfCentralDirectory int
,@NumberOfWorksheets smallint
,@CurrentWorksheet smallint = 1
,@sql nvarchar(max) = N''
,@rowcountsql nvarchar(max)
,@rowcount int
,@colcount int
,@datatable varchar(100)
,@RowDataXML nvarchar(max)
,@SelectOutput bit = 0
,@ArchiveInfo binary(10)
,@WorksheetFileName varchar(50)
,@ObjectToken int
,@AutoFilterXML nvarchar(max) = N''
,@_Content_Types__xml__sheets nvarchar(max)
,@_Content_Types__xml varbinary(max)
,@Workbook_xml_temp nvarchar(max)
,@Workbook_xml varbinary(max)
,@_Rels_workbook_xml_rels varbinary(max)
,@styles_xml varbinary(max) = cast(N'<?xml version="1.0" encoding="utf-16"?>
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<numFmts count="3">
<numFmt formatCode="dd/mm/yyyy\ hh:mm" numFmtId="165"/>
<numFmt formatCode="hh:mm" numFmtId="166"/>
<numFmt formatCode="dd/mm/yyyy" numFmtId="167"/>
</numFmts>
<fonts count="7">
<font> <sz val="11"/> <name val="Calibri"/><family val="2" /><scheme val="minor" /></font>
<font> <sz val="11"/><color rgb="FFFF0000" /><name val="Calibri"/><family val="2" /><scheme val="minor" /></font>
<font><b/><sz val="11"/> <name val="Calibri"/><family val="2" /><scheme val="minor" /></font>
<font><i/><sz val="11"/> <name val="Calibri"/><family val="2" /><scheme val="minor" /></font>
<font> <sz val="11"/><color rgb="FF0070C0" /><name val="Calibri"/><family val="2" /><scheme val="minor" /></font>
<font> <sz val="20"/> <name val="Calibri"/><family val="2" /><scheme val="minor" /></font>
<font> <sz val="11"/> <name val="Courier"/><family val="3" /> </font>
</fonts>
<fills count="2">
<fill>
<patternFill patternType="none" />
</fill>
<fill>
<patternFill patternType="gray125" />
</fill>
</fills>
<borders count="1">
<border>
<left />
<right />
<top />
<bottom />
<diagonal />
</border>
</borders>
<cellStyleXfs count="1">
<xf numFmtId="0" fontId="0" fillId="0" borderId="0" />
</cellStyleXfs>
<cellXfs count="10">
<xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0" />
<xf numFmtId="0" fontId="2" fillId="0" borderId="0" xfId="0" applyFont="1" />
<xf numFmtId="0" fontId="3" fillId="0" borderId="0" xfId="0" applyFont="1" />
<xf numFmtId="0" fontId="4" fillId="0" borderId="0" xfId="0" applyFont="1" />
<xf numFmtId="0" fontId="1" fillId="0" borderId="0" xfId="0" applyFont="1" />
<xf numFmtId="0" fontId="5" fillId="0" borderId="0" xfId="0" applyFont="1" />
<xf numFmtId="0" fontId="6" fillId="0" borderId="0" xfId="0" applyFont="1" />
<xf numFmtId="165" borderId="0" fillId="0" fontId="0" xfId="0" applyNumberFormat="1"/>
<xf numFmtId="166" borderId="0" fillId="0" fontId="0" xfId="0" applyNumberFormat="1"/>
<xf numFmtId="167" borderId="0" fillId="0" fontId="0" xfId="0" applyNumberFormat="1"/>
</cellXfs>
<cellStyles count="1">
<cellStyle name="Standard" xfId="0" builtinId="0" />
</cellStyles>
<dxfs count="0" />
<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleLight16" />
</styleSheet>' as varbinary(max))
,@worksheet_xml varbinary(max)
,@_rels_rels varbinary(max) = cast(N'<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="workbook.xml"/>
</Relationships>' as varbinary(max));
-- if Worksheets is not specified, set @Worksheets to @SheetName + / + #data
if @Worksheets is null-- @SheetName is not null and @Worksheets is null
set @Worksheets = IsNull(@SheetName, 'Sheet1') + '/#data';
-- if a non-null value is passed in @WorkbookData, the output should be set in the optional output parameter @WorkbookData
-- if a null or no value is passed in @WorkbookData, the output will be selected at the end of the procedure
if @WorkbookData is null and @OutputFileName is null
set @SelectOutput = 1
else
set @WorkbookData = null;
select
Worksheet.ValueOrder as WorksheetNumber
,WorksheetTable.ValueOrder as ColumnNumber
,WorksheetTable.value
,WorksheetTableOptions.ValueOrder as WorksheetOptionNumber
,WorksheetTableOptions.value as WorksheetOption
into #WorksheetConfig
from dbo.StringSplit2(@Worksheets, '|') as Worksheet
cross apply dbo.StringSplit2(Worksheet.value, '/') as WorksheetTable
cross apply dbo.StringSplit2(WorksheetTable.value, '~') as WorksheetTableOptions;
select
@NumberOfWorksheets = max(WorksheetNumber)
from #WorksheetConfig;
-- xml for @Workbook_xml
with xmlnamespaces (
'http://schemas.openxmlformats.org/officeDocument/2006/relationships' as r
,default 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
)
select @Workbook_xml_temp = (
select
Worksheet.value as [sheet/@name]
,Worksheet.WorksheetNumber as [sheet/@sheetId]
,'rId' + cast(Worksheet.WorksheetNumber + 1 as varchar) as [sheet/@r:id]
from #WorksheetConfig Worksheet
where ColumnNumber = 1
for xml path('sheets'), root('workbook')
);
set @Workbook_xml = cast(Replace(@Workbook_xml_temp, '</sheets><sheets>', '') as varbinary(max));
-- xml for @_Content_Types__xml
select @_Content_Types__xml__sheets = (
select
'/sheet' + cast(Worksheet.WorksheetNumber as varchar) + '.xml' as [@PartName]
,'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml' as [@ContentType]
from #WorksheetConfig Worksheet
where ColumnNumber = 1
for xml path('Override')
);
-- xml for @_Rels_workbook_xml_rels
with xmlnamespaces (
default 'http://schemas.openxmlformats.org/package/2006/relationships'
)
,x as (
select
'rId1' as [@Id]
,'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles' as [@Type]
,'styles.xml' as [@Target]
union all
select
'rId' + cast(Worksheet.WorksheetNumber + 1 as varchar) as [@Id]
,'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet' as [@Type]
,'sheet' + cast(Worksheet.WorksheetNumber as varchar) + '.xml' as [@Target]
from #WorksheetConfig Worksheet
where ColumnNumber = 1
)
select @_Rels_workbook_xml_rels = cast((
select
*
from x
for xml path('Relationship'), root('Relationships')
) as varbinary(max));
set @_Content_Types__xml = cast(N'<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Override PartName="/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
' + @_Content_Types__xml__sheets + '
</Types>' as varbinary(max));
exec dbo.AddFileToArchive
@FileName = '[Content_Types].xml'
,@FileContents = @_Content_Types__xml
,@ArchiveData = @WorkbookData output
,@ArchiveInfo = @ArchiveInfo output;
exec dbo.AddFileToArchive
@FileName = '_rels/.rels'
,@FileContents = @_rels_rels
,@ArchiveData = @WorkbookData output
,@ArchiveInfo = @ArchiveInfo output;
exec dbo.AddFileToArchive
@FileName = '_rels/workbook.xml.rels'
,@FileContents = @_Rels_workbook_xml_rels
,@ArchiveData = @WorkbookData output
,@ArchiveInfo = @ArchiveInfo output;
exec dbo.AddFileToArchive
@FileName = 'workbook.xml'
,@FileContents = @workbook_xml
,@ArchiveData = @WorkbookData output
,@ArchiveInfo = @ArchiveInfo output;
exec dbo.AddFileToArchive
@FileName = 'styles.xml'
,@FileContents = @styles_xml
,@ArchiveData = @WorkbookData output
,@ArchiveInfo = @ArchiveInfo output;
while @CurrentWorksheet <= @NumberOfWorksheets
begin
set @sql = '';
select
@datatable = value
from #WorksheetConfig
where WorksheetNumber = @CurrentWorksheet
and ColumnNumber = 2;
select @sql +=
',''' + rtrim(case when column_id > 26 then char(64 + ((column_id -1) / 26)) + char(65 + ((column_id -1) % 26)) else char(64 + column_id) end) + ''' + cast(__r__ as varchar) as [c/@r]'
+ case when sc.system_type_id in (40, 41, 42, 43, 48, 52, 56, 58, 61, 62, 104, 106, 108, 127) then '' else ',''inlineStr'' as [c/@t]' end -- non text data types
+ case
when sc.system_type_id in (42, 43, 58, 61) then ',7 as [c/@s]' -- datetime2, datetimeoffset smalldatetime, datetime
when sc.system_type_id in (41) then ',8 as [c/@s]' -- time
when sc.system_type_id in (40) then ',9 as [c/@s]' -- date
else ''
end -- smalldatetime, datetime, time, date
+ ',' + case
when sc.system_type_id in (40, 58, 61) then 'cast(cast(' + quotename(name) + 'as datetime) as float) + case when ''19000301'' > ' + quotename(name) + ' then 1 else 2 end'
when sc.system_type_id in (42, 43) then 'cast(cast(cast(' + quotename(name) + ' as date) as datetime) as float) + datepart(hh, ' + quotename(name) + ') / 24.00000 + datepart(mi, ' + quotename(name) + ') / 1440.00000 + datepart(ss, ' + quotename(name) + ') / 86400.00000 + datepart(ms, ' + quotename(name) + ') / 86400000.00000 + case when ''19000301'' > ' + quotename(name) + ' then 1 else 2 end'
when sc.system_type_id in (41) then 'cast(cast(' + quotename(name) + ' as datetime) as float)' else quotename(name)
end
+ case when sc.system_type_id in (40, 41, 42, 43, 48, 52, 56, 58, 61, 62, 104, 106, 108, 127) then ' as [c/v]' else ' as [c/is/t]' end
+ ','''''
from tempdb.sys.columns sc
where object_id = object_id('tempdb.dbo.' + @datatable)
order by column_id;
set @sql = right(@sql, len(@sql) - 1);
set @sql =
'select @xml = (select(cast((
select
1 as [@r]
,(
select
rtrim(case when column_id > 26 then char(64 + ((column_id -1) / 26)) + char(65 + ((column_id -1) % 26)) else char(64 + column_id) end) + ''1'' as [c/@r]
,1 as [c/@s]
,''inlineStr'' as [c/@t]
,name as [c/is/t]
from tempdb.sys.columns sc
where object_id = object_id(''' + case when left(@datatable, 1) = '#' then 'tempdb.dbo.' else '' end + Replace(@datatable, '''', '''''') + ''')
order by column_id
for xml path(''''), type
)
from (select 1 as c1) x
for xml path(''row''))
as nvarchar(max))))
+
(select(IsNull(cast((
select
__r__ as [@r]
,(
select
' + @sql + '
for xml path(''''), type
)
from (select row_number() over (order by (select 1)) + 1 as __r__, * from ' + Replace(@datatable, '''', '''''') + ') d
for xml path(''row''))
as nvarchar(max)), '''')));';
exec sp_executesql @stmt = @sql, @params = N'@xml nvarchar(max) output', @xml = @RowDataXML output;
if exists (select * from #WorksheetConfig where WorksheetNumber = @CurrentWorksheet and ColumnNumber = 3 and WorksheetOption = 'autofilter')
begin
set @rowcountsql = N'select @rowcount = count(*) + 1 from ' + @datatable;
exec sp_executesql @stmt = @rowcountsql, @params = N'@rowcount int output', @rowcount = @rowcount output;
select
@colcount = count(*)
from tempdb.sys.columns sc
where object_id = object_id('tempdb.dbo.' + @datatable);
select @AutoFilterXML = N'<autoFilter ref="A1:'
+ rtrim(case when @colcount > 26 then char(64 + ((@colcount -1) / 26)) + char(65 + ((@colcount -1) % 26)) else char(64 + @colcount) end) + cast(@rowcount as nvarchar)
+ '" xr:uid="{' + cast(newid() as nvarchar(36)) + '}"/>';
end;
set @worksheet_xml = cast(
'<?xml version="1.0" encoding="UTF-16" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision"><sheetData>' + @RowDataXML + '</sheetData>' + @AutoFilterXML + '</worksheet>'
as varbinary(max));
set @WorksheetFileName = 'sheet' + cast(@CurrentWorksheet as varchar) + '.xml';
exec dbo.AddFileToArchive
@FileName = @WorksheetFileName
,@FileContents = @worksheet_xml
,@ArchiveData = @WorkbookData output
,@ArchiveInfo = @ArchiveInfo output;
set @CurrentWorksheet = @CurrentWorksheet +1;
set @AutoFilterXML = N'';
end;
if @SelectOutput = 1
select @WorkbookData as ExcelSpreadsheetData;
if @OutputFileName is not null and (select value_in_use from sys.configurations where name = 'Ole Automation Procedures') = 1
begin
exec sp_oacreate 'ADODB.Stream', @ObjectToken output;
exec sp_oasetproperty @ObjectToken, 'type', 1;
exec sp_oamethod @ObjectToken, 'open';
exec sp_oamethod @ObjectToken, 'write', null, @WorkbookData;
exec sp_oamethod @ObjectToken, 'savetofile', null, @OutputFileName, 2;
exec sp_oamethod @ObjectToken, 'close';
exec sp_oadestroy @ObjectToken;
end;
return;
GO
使用例:
select * into #systables from sys.tables;
select * into #syscolumns from sys.columns;
select * into #systypes from sys.types;
exec dbo.GetExcelSpreadsheetData
@Worksheets = 'sys.tables/#systables/autofilter|sys.columns/#syscolumns/autofilter|sys.types/#systypes'
,@OutputFileName = 'c:\tmp\ExcelData.xlsx';
drop table #systables;
drop table #syscolumns;
drop table #systypes;
編集:これはTSQLで行うのはばかげたことだとコメントする人には同意します。当時は悪い考えのようでしたが、それは私の人生を楽にしてくれます。