Skip to content

Commit eb40efb

Browse files
committed
Added script
1 parent fa5b44a commit eb40efb

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# PowerShell script to generate a SQL CREATE TABLE statement from an Excel file
2+
Write-Host "=== GENERATE CREATE TABLE FROM EXCEL ==="
3+
4+
# --- XLSX File Selection ---
5+
$scriptDir = $PSScriptRoot
6+
$excelFiles = Get-ChildItem -Path $scriptDir -Filter *.xlsx
7+
8+
if (-not $excelFiles -or $excelFiles.Count -eq 0) {
9+
Write-Error "No .xlsx file found in: $scriptDir"
10+
exit 1
11+
}
12+
13+
if ($excelFiles.Count -eq 1) {
14+
$ExcelFile = $excelFiles[0]
15+
Write-Host "Excel file selected: $($ExcelFile.Name)"
16+
} else {
17+
Write-Host "Multiple .xlsx files found in the folder:"
18+
for ($i = 0; $i -lt $excelFiles.Count; $i++) {
19+
Write-Host "[$i] $($excelFiles[$i].Name)"
20+
}
21+
$fileIndex = Read-Host "Enter the number of the Excel file to use"
22+
if ($fileIndex -notmatch '^\d+$' -or [int]$fileIndex -lt 0 -or [int]$fileIndex -ge $excelFiles.Count) {
23+
Write-Error "Invalid selection. Exiting."
24+
exit 1
25+
}
26+
$ExcelFile = $excelFiles[$fileIndex]
27+
Write-Host "Excel file selected: $($ExcelFile.Name)"
28+
}
29+
30+
# --- Sheet Name ---
31+
$SheetName = Read-Host "Enter the Excel sheet name (SheetName)"
32+
if ([string]::IsNullOrWhiteSpace($SheetName)) {
33+
Write-Error "SheetName not provided. Exiting script."
34+
exit 1
35+
}
36+
37+
# --- SQL Table Name ---
38+
$SqlTableName = Read-Host "Enter the SQL table name (SqlTableName)"
39+
if ([string]::IsNullOrWhiteSpace($SqlTableName)) {
40+
Write-Error "SqlTableName not provided. Exiting script."
41+
exit 1
42+
}
43+
44+
# --- Output File Name ---
45+
$defaultOutput = "create_table.txt"
46+
$outputInput = Read-Host "Enter the output file name (press Enter for default: $defaultOutput)"
47+
if ([string]::IsNullOrWhiteSpace($outputInput)) {
48+
$OutputFile = Join-Path $PSScriptRoot $defaultOutput
49+
} else {
50+
$OutputFile = Join-Path $PSScriptRoot $outputInput
51+
}
52+
53+
# --- Type Detection Threshold ---
54+
$defaultThreshold = 500
55+
$thresholdInput = Read-Host "Enter threshold for type detection (press Enter for default: $defaultThreshold)"
56+
if ([string]::IsNullOrWhiteSpace($thresholdInput)) {
57+
$TypeThreshold = $defaultThreshold
58+
} else {
59+
if ($thresholdInput -as [int]) {
60+
$TypeThreshold = [int]$thresholdInput
61+
} else {
62+
Write-Error "Invalid threshold. Using default value: $defaultThreshold"
63+
$TypeThreshold = $defaultThreshold
64+
}
65+
}
66+
67+
Write-Host "Excel file: $($ExcelFile.FullName)"
68+
Write-Host "Sheet: $SheetName"
69+
Write-Host "SQL table: $SqlTableName"
70+
Write-Host "Output: $OutputFile"
71+
72+
# --- ImportExcel Module ---
73+
if (-not (Get-Module -ListAvailable -Name ImportExcel)) {
74+
Install-Module -Name ImportExcel -Scope CurrentUser -Force
75+
}
76+
Import-Module ImportExcel
77+
78+
# --- Read Data from Sheet ---
79+
try {
80+
$data = Import-Excel -Path $ExcelFile.FullName -WorksheetName $SheetName
81+
} catch {
82+
Write-Error "Error importing XLSX file: $($_.Exception.Message)"
83+
exit 1
84+
}
85+
if (-not $data -or $data.Count -eq 0) {
86+
Write-Error "Sheet is empty or unreadable."
87+
exit 1
88+
}
89+
90+
# --- Get Actual Column Names ---
91+
$columnNames = $data | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
92+
93+
# --- Handle Duplicate Headers ---
94+
$finalHeaders = @()
95+
$uniqueHeaders = @{}
96+
$duplicates = @()
97+
foreach ($c in $columnNames) {
98+
$colName = if ($null -eq $c -or "$c".Trim() -eq "") { "UnnamedColumn" } else { "$c".Trim() }
99+
$baseName = $colName
100+
$i = 2
101+
while ($finalHeaders -contains $colName) {
102+
if (-not ($duplicates -contains $baseName)) { $duplicates += $baseName }
103+
$colName = "${baseName}_$i"; $i++
104+
}
105+
$finalHeaders += $colName
106+
$uniqueHeaders[$finalHeaders.Count - 1] = $colName
107+
}
108+
if ($duplicates.Count -gt 0) {
109+
Write-Host "WARNING: Duplicate columns found and renamed: $($duplicates -join ', ')"
110+
} else {
111+
Write-Host "No duplicate columns detected."
112+
}
113+
114+
function Get-SqlTypeAndLength($colName, $values) {
115+
# Clean: convert all to string, remove nulls and empty/whitespace strings
116+
$cleanValues = $values | Where-Object { $_ -ne $null } | ForEach-Object { "$_".Trim() }
117+
$nonNullValues = $cleanValues | Where-Object { $_ -match '\S' }
118+
119+
if ($nonNullValues.Count -eq 0) {
120+
if ($colName -match '(?i)data|date') { return @{Type="DATETIME"; Length=$null} }
121+
else { return @{Type="NVARCHAR"; Length=100} }
122+
}
123+
124+
$intCount = ($nonNullValues | Where-Object { $_ -match '^-?\d+$' } | Measure-Object).Count
125+
$floatCount = ($nonNullValues | Where-Object { $_ -match '^-?\d+\.\d+$' } | Measure-Object).Count
126+
$dateCount = ($nonNullValues | Where-Object {
127+
try { [datetime]::Parse($_) | Out-Null; $true } catch { $false }
128+
} | Measure-Object).Count
129+
$boolCount = ($nonNullValues | Where-Object {
130+
$t = $_.ToLower()
131+
$t -eq "true" -or $t -eq "false" -or $t -eq "0" -or $t -eq "1"
132+
} | Measure-Object).Count
133+
134+
if ($intCount -ge $TypeThreshold -and $intCount -eq $nonNullValues.Count) {
135+
return @{Type="INT"; Length=$null}
136+
} elseif ($boolCount -ge $TypeThreshold -and $boolCount -eq $nonNullValues.Count) {
137+
return @{Type="BIT"; Length=$null}
138+
} elseif ($floatCount -ge $TypeThreshold -and $floatCount -eq $nonNullValues.Count) {
139+
return @{Type="FLOAT"; Length=$null}
140+
} elseif ($dateCount -ge $TypeThreshold -and $dateCount -eq $nonNullValues.Count) {
141+
return @{Type="DATETIME"; Length=$null}
142+
} else {
143+
# NVARCHAR: calculate max length
144+
$maxLen = ($nonNullValues | ForEach-Object { $_.Length } | Measure-Object -Maximum).Maximum
145+
$maxAllowed = 255
146+
$colLength = [Math]::Min($maxLen, $maxAllowed)
147+
return @{Type="NVARCHAR"; Length=$colLength}
148+
}
149+
}
150+
151+
# --- Analyze Columns and Detect SQL Types ---
152+
$Columns = @()
153+
for ($i = 0; $i -lt $finalHeaders.Count; $i++) {
154+
$colName = $finalHeaders[$i]
155+
$propName = $columnNames[$i]
156+
$values = @()
157+
foreach ($row in $data) {
158+
$cellValue = $row.$propName
159+
$values += $cellValue
160+
}
161+
$typeInfo = Get-SqlTypeAndLength $colName $values
162+
$CleanCol = $colName -replace '[^a-zA-Z0-9_]', '_'
163+
$sqlType = if ($typeInfo.Type -eq "NVARCHAR") { "NVARCHAR($($typeInfo.Length))" } else { $typeInfo.Type }
164+
Write-Host "$colName -> $sqlType"
165+
$Columns += "[$CleanCol] $sqlType"
166+
}
167+
168+
$ColumnsSql = $Columns -join ",`n "
169+
$CreateTable = "CREATE TABLE [$SqlTableName] (`n $ColumnsSql`n);"
170+
171+
Set-Content -Path $OutputFile -Value $CreateTable -Encoding UTF8
172+
Write-Host "SQL command generated and saved to: $OutputFile"
173+
174+
# --- Output Preview ---
175+
Write-Host "=== OUTPUT FILE CONTENT: $OutputFile ==="
176+
Get-Content -Path $OutputFile | Write-Host
177+
178+
Write-Host "=== END OF SCRIPT ==="

0 commit comments

Comments
 (0)