• úvod
  • témata
  • události
  • tržiště
  • diskuze
  • nástěnka
  • přihlásit
    registrace
    ztracené heslo?
    LUCIENVibe coding
    REDSNAKE
    REDSNAKE --- ---
    Jak ten codex pouzivate prakticky? Jde to naroubovat nak bezbolestne do ide?
    MARASAN
    MARASAN --- ---
    SKAFF: codex je od koho?
    SKAFF
    SKAFF --- ---
    potřeboval jsem docknout header, aby mi zůstal kde je při vertikálním scrollu.

    opus 4.6 - sežral asi 20% denního bugetu a chcípnul
    sonnet 4.6 - refaktoroval 10 souborů, vytvořil x funkcí a změnil kompletně rendering a strukturu v headeru a stejně to posral

    Codex 5.3:

    Done. Je to sranda příklad, ale je asi fajn vystoupit někdy z bubliny :)

    TLOUDEV
    TLOUDEV --- ---
    TOXICMAN: claude code mam na virtualu, kterej je voklestenej, takze ixkovy veci jedu pres webchat... no boze.
    TOXICMAN
    TOXICMAN --- ---
    TLOUDEV: webový chat není uplně to správné místo :)
    TLOUDEV
    TLOUDEV --- ---
    :-)

    LUCIEN
    LUCIEN --- ---
    REDSNAKE: Za mě Claude zatím asi top. Ale neplatím si ho, platí firma, tak nevím jak je na tom cenově s konkurencí.
    KAPPI
    KAPPI --- ---
    Kdyby někdo řešil, jak dostat svoji filmovou knihovnu ve 4K na flash disk a přehrávat ji na Apple zařízeních (nejen těch) bez překódování, měl NVIDIA GPU a spoustu času — https://github.com/kappi/transcoder-control

    Je to Docker image, takže extra jednoduché na zprovoznění (testováno na linux hostu, na win by to mělo taky fungovat, ale bude to chtít si s tím pohrát kvůli nvidia driveru).

    Dělal jsem to s Claudem, dlouze testoval a vychytal snad všechny mouchy. A že jich bylo — těch kombinací formátů videí, titulků atd…

    Nápad na převod videotéky jsem měl už dlouho, chtěl jsem mít vše kompaktní na cesty. Další projekt, který plánuji, je nějaká ARM deska s podporou NVMe SSD, na které poběží Jellyfin, bude dělat Wi-Fi hotspot a budeme se na to s přáteli připojovat a koukat každý na to, na co bude chtít — hlavně na dlouhých přeplavbách na lodi :D

    Proto mi šlo o co nejkompaktnější, stále dobře sledovatelné 720p ve formátu pro Direct Play na iOS.

    Jedna z podstatných věcí je, že zachovávám audiostopy pouze s vybranými jazyky — CZ, EN, JP a CHI (výběr se dá změnit v transcoder.py). Pokud ani jeden není ve videu přítomen nebo není správně označený, zachovají se všechny dostupné.
    Titulky zachovávám všechny, které jsou. Pokud je film nějaké anime a má titulky v ASS/SAA formatu (ruzna grafika a šaškárny), tak je převedu do klasického textu a nacpu do mp4 kontejneru k filmu. Zároveň původní ASS formát vyextrahuju vedle do souboru a přiložím. Dají se potom použít v přehrávači, který je podporuje (třeba jellyfin a VLC to umí a vezme si je).

    Tak třeba se to někomu taky hodí :D
    REDSNAKE
    REDSNAKE --- ---
    Chystám se na refaktor jedné aplikace a rád bych si předplatil nějaký startovací tier nějaké služby. Chvíli jsem z toho vypadl a jak všichni víme, podmínky, nabídky a trh se mění - budu rád když se podělíte o aktuální zkušenost kdo dává nejlepší kvoty a s čím jste spokojení.

    Díky!
    SKAFF
    SKAFF --- ---
    Tohle jsem "napsal" po večerech a během března do toho onboarduju v testu dva (velký) enterprise klienty, který klasicky vedou produktový / projektový development v excelu - zatím jako interní tool, s plánem to rolloutnout ven (securita, db performance, audity - ještě relativne dlouhá cesta, ale...)

    Je velmi možný, že monday / notion jsou turbofucked. Ne kvuli mě nebo že by tohle byla konkurence - je to přecejen dost simple, ale kvuli tomu, že tohle je možný. 0% napsano mnou - nejsem dev.

    Organizační struktura a user managment s řadou Auth providerů (Entra, Google atd)
    Dynamický dashboardy
    Zcela custom EAV
    Realtime collab
    Table + Timeline
    Audit logy
    Detail panel se 100% customizovatelným views
    Importy z excelu
    Exporty do excelu
    Synced dash (tj dá se to použít jako zobrazovátko z existujícího toolu)
    Unsynced dash (tj content si naleju sám a udržuju)





    CMLKA
    CMLKA --- ---
    JEREMIUS: claude code jde na Antigravity napojit přímo
    TOM
    TOM --- ---
    JEREMIUS: 16€ měsíčně (verze Pro, roční platba) je nic, platím to ze svého... a platil bych klidně i 10x víc
    tak až ti dojdou nervy s gemini, víš, co vyzkoušet ;)
    JEREMIUS
    JEREMIUS --- ---
    TOM: No Claude si platit nebudu, když už mám Gemini :-) Ale na Zandla jsem ještě nenarazil, koukám se, že ten borec taky dělá do všeho. Mrknu na to, počítám, že to půjde použít s modifikací na Google alternativy
    TOM
    TOM --- ---
    JEREMIUS: placené jako v práci? Mám taky, občas si porovnávám totožný prompt na nějaký jednodušší (relativně) úkol, a z geminy/chatgpt/claude vyhrává vždycky claude.
    https://youtube.com/playlist?list=PLhQUMNDqmMREKeByxOtIt-6gnj2TB1VXK
    JEREMIUS
    JEREMIUS --- ---
    Nemáte tip na nějaký ultimátní tutorial do vibe codingu, který by shrnul vše podstatné? Zkoušel jsem nějaké skripty klasicky v chatu. Nyní dělám věci v Antigravity (mám placené Gemini), ale už nějak nevím, jestli/proč zkoušel Jules nebo CLI. A vlastně nemám moc přehled, jak tu AI ideálně proptovat, dělám to zatím spíš jen pocitově a využívám toho, že jsem kdysi programoval. Zkoušel jsem pár videjí, ale jsou to vždycky jen nějaké divné střípky, nic uceleného. Předem díky
    PLECH
    PLECH --- ---
    Jakožto aktivní vývojář programující 27 let Vibe codingu moc neholduju, ale zkusil jsem for fun napsat python aparát čistě pomocí chat gpt, včetně dockerfilu a docker run příkazu.

    Skript kouká každých deset minut na RSS feed z Instagramu Nathana Pyla, potom pomocí vision api zjišťuje, jestli jsou obrázky Strange Planet komiksy nebo jen random džouky, a následně pomocí nyx api obrázky vkládá do auditka níže. Ukládá si persistentně stav, aby neduplikoval posty.
    [Regularly Scheduled Humor Rectangles :: Strange Planet auto feed]

    Fungje to.
    TOM
    TOM --- ---
    TOM: oprava UTF-8 a detekce/použití separátoru

    @@ echo off
    @@ echo Invoking a Powershell script...
    @@ setlocal
    @@ set PS_WRAPPER_ARGS=%*
    @@ set PS_WRAPPER_PATH=%~f0
    @@ if defined PS_WRAPPER_ARGS set PS_WRAPPER_ARGS=%PS_WRAPPER_ARGS:"="%
    @@ PowerShell -sta -Command Invoke-Expression $('$args=@(^&{$args} %PS_WRAPPER_ARGS%);'+[String]::Join([Environment]::NewLine,$((Get-Content '%PS_WRAPPER_PATH%') -notmatch '^^@@^|^^:^|^^cls'))) & endlocal & cmd /k
    
    Add-Type -AssemblyName System.Windows.Forms, PresentationFramework, WindowsBase
    
    Add-Type @"
    using System;
    using System.Runtime.InteropServices;
    
    public class DarkMode {
        [DllImport("dwmapi.dll")]
        public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
    }
    "@
    
    # Dark mode detection
    function Get-WindowsTheme {
        try {
            $path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize"
            $value = Get-ItemProperty -Path $path -Name "AppsUseLightTheme" -ErrorAction Stop
            return $value.AppsUseLightTheme -eq 0
        } catch {
            return $false
        }
    }
    
    # Initialize theme-specific colors
    $script:isDarkMode = Get-WindowsTheme
    $darkBackColor = [System.Drawing.Color]::FromArgb(32, 32, 32)
    $darkForeColor = [System.Drawing.Color]::FromArgb(240, 240, 240)
    $darkControlBackColor = [System.Drawing.Color]::FromArgb(45, 45, 45)
    
    # Fix: Use theme-specific accent colors for proper visibility
    $script:accentColor = if ($script:isDarkMode) { 
        [System.Drawing.Color]::FromArgb(120, 250, 174)  # Light green for dark mode
    } else { 
        [System.Drawing.Color]::FromArgb(0, 120, 50)     # Darker green for light mode
    }
    
    # Character replacement mapping (using character codes to avoid UTF-8 encoding issues)
    $script:charMap = @{
        [char]0x00E4 = 'ae'; [char]0x00F6 = 'oe'; [char]0x00FC = 'ue'; [char]0x00E9 = 'e'
        [char]0x00E8 = 'e'; [char]0x00EA = 'e'; [char]0x011B = 'e'; [char]0x00E0 = 'a'
        [char]0x00C4 = 'AE'; [char]0x00D6 = 'OE'; [char]0x00DC = 'UE'; [char]0x00C9 = 'E'
        [char]0x00C8 = 'E'; [char]0x00CA = 'E'; [char]0x011A = 'E'; [char]0x00C0 = 'A'
        [char]0x00E1 = 'a'; [char]0x010D = 'c'; [char]0x010F = 'd'; [char]0x00ED = 'i'
        [char]0x0148 = 'n'; [char]0x00F3 = 'o'; [char]0x0159 = 'r'; [char]0x0161 = 's'
        [char]0x0165 = 't'; [char]0x016F = 'u'; [char]0x00FA = 'u'; [char]0x00FD = 'y'
        [char]0x017E = 'z'; [char]0x0142 = 'l'; [char]0x0111 = 'd'
        [char]0x00C1 = 'A'; [char]0x010C = 'C'; [char]0x010E = 'D'; [char]0x00CD = 'I'
        [char]0x0147 = 'N'; [char]0x00D3 = 'O'; [char]0x0158 = 'R'; [char]0x0160 = 'S'
        [char]0x0164 = 'T'; [char]0x016E = 'U'; [char]0x00DA = 'U'; [char]0x00DD = 'Y'
        [char]0x017D = 'Z'; [char]0x0141 = 'L'; [char]0x0110 = 'D'
        [char]0x00DF = 'ss'; ',' = '_'; ' ' = '_'; '.' = '_'; '!' = '_'; [char]0x00A7 = '_'
        "'" = '_'; [char]0x00B4 = '_'; [char]0x02C7 = '_'; ';' = '_'; '(' = '_'; ')' = '_'; '-' = '_'
    }
    
    # Function to sanitize sheet names
    function Sanitize-SheetName {
        param([string]$name)
        
        $result = $name
        foreach ($key in $script:charMap.Keys) {
            $result = $result -replace [regex]::Escape($key), $script:charMap[$key]
        }
        return $result
    }
    
    # Function to process a single Excel file
    function Process-ExcelFile {
        param(
            [string]$filePath,
            [System.Windows.Forms.TextBox]$logBox = $null
        )
        
        $excel = $null
        $workbook = $null
        
        try {
            # Validate file
            if (-not (Test-Path $filePath)) {
                $msg = "ERROR: File not found: $filePath"
                if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
                return
            }
            
            if ($filePath -notmatch "\.(xlsx|xlsm|xls)$") {
                $msg = "ERROR: Not an Excel file: $filePath"
                if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
                return
            }
            
            $msg = "Processing: $filePath"
            if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
            
            # Create output folder
            $fileInfo = Get-Item $filePath
            $folderName = [System.IO.Path]::GetFileNameWithoutExtension($fileInfo.Name)
            $outputFolder = Join-Path $fileInfo.DirectoryName $folderName
            
            if (-not (Test-Path $outputFolder)) {
                [void](New-Item -ItemType Directory -Path $outputFolder -Force)
                $msg = "Created folder: $outputFolder"
                if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
            }
            
            # Open Excel
            $excel = New-Object -ComObject Excel.Application
            $excel.Visible = $false
            $excel.DisplayAlerts = $false
            $excel.ScreenUpdating = $false
            
            $workbook = $excel.Workbooks.Open($filePath)
            $sheetCount = $workbook.Sheets.Count
            
            $msg = "Found $sheetCount sheet(s)"
            if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
            
            # Get system list separator for proper CSV format
            $listSeparator = (Get-Culture).TextInfo.ListSeparator
            
            # Export each sheet and collect info for markdown
            $sheetInfo = @()
            for ($i = 1; $i -le $sheetCount; $i++) {
                $sheet = $workbook.Sheets.Item($i)
                $sheetName = $sheet.Name
                $sanitizedName = Sanitize-SheetName $sheetName
                $csvPath = Join-Path $outputFolder "$sanitizedName.csv"
                
                $msg = "  Exporting sheet '$sheetName' -> '$sanitizedName.csv'"
                if ($logBox) { 
                    $logBox.AppendText("$msg`r`n")
                    [System.Windows.Forms.Application]::DoEvents()
                } else { 
                    Write-Host $msg 
                }
                
                # Manual CSV export to preserve formatting and use system separator
                $usedRange = $sheet.UsedRange
                if ($usedRange -ne $null) {
                    $rowCount = $usedRange.Rows.Count
                    $colCount = $usedRange.Columns.Count
                    
                    # Build CSV content line by line
                    $csvLines = @()
                    for ($row = 1; $row -le $rowCount; $row++) {
                        $rowValues = @()
                        for ($col = 1; $col -le $colCount; $col++) {
                            $cell = $sheet.Cells.Item($row, $col)
                            $text = $cell.Text  # Get formatted display value (preserves dates as DD.MM.YYYY)
                            
                            # Escape if contains separator, quotes, or newlines
                            if ($text -match "[$([regex]::Escape($listSeparator))`"`r`n]") {
                                $text = '"' + ($text -replace '"', '""') + '"'
                            }
                            $rowValues += $text
                            
                            # Release cell COM object
                            [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($cell)
                        }
                        $csvLines += ($rowValues -join $listSeparator)
                    }
                    
                    # Write CSV with UTF-8 encoding
                    $csvLines -join "`r`n" | Set-Content -Path $csvPath -Encoding UTF8
                    
                    # Release range COM object
                    [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($usedRange)
                }
                
                # Store info for markdown
                $sheetInfo += [PSCustomObject]@{
                    OriginalName = $sheetName
                    SanitizedName = $sanitizedName
                    CsvPath = $csvPath
                }
                
                # Release sheet COM object
                [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($sheet)
            }
            
            # Create combined markdown file
            $msg = "`r`n  Creating combined markdown file..."
            if ($logBox) { 
                $logBox.AppendText("$msg`r`n")
                [System.Windows.Forms.Application]::DoEvents()
            } else { 
                Write-Host $msg 
            }
            
            $markdownPath = Join-Path $outputFolder "$folderName.md"
            $markdownContent = ""
            
            foreach ($info in $sheetInfo) {
                $markdownContent += "# $($info.OriginalName)`r`n"
                if (Test-Path $info.CsvPath) {
                    $csvContent = Get-Content -Path $info.CsvPath -Raw -Encoding UTF8
                    $markdownContent += $csvContent.TrimEnd() + "`r`n`r`n"
                }
            }
            
            $markdownContent | Set-Content -Path $markdownPath -Encoding UTF8
            
            $msg = "`r`nSuccess! Exported $sheetCount sheet(s) to: $outputFolder`r`n"
            $msg += "  - Individual CSV files: $sheetCount`r`n"
            $msg += "  - Combined markdown: $folderName.md`r`n"
            $msg += "  - Using delimiter: '$listSeparator'`r`n"
            if ($logBox) { $logBox.AppendText("$msg") } else { Write-Host $msg }
            
        } catch {
            $msg = "ERROR: $_"
            if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
        } finally {
            # Cleanup COM objects (critical!)
            if ($workbook -ne $null) {
                $workbook.Close($false)
                [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($workbook)
            }
            
            if ($excel -ne $null) {
                $excel.Quit()
                [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel)
            }
            
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
            Start-Sleep -Milliseconds 500
        }
    }
    
    # Main logic: Check if file was drag-dropped
    if ($args.Count -gt 0 -and $args[0]) {
        # Silent mode - no GUI
        $filePath = $args[0]
        Process-ExcelFile -filePath $filePath
        
    } else {
        # GUI mode - no file provided
        
        # Create main form
        $form = New-Object Windows.Forms.Form
        $form.Text = "Excel to CSV Exporter"
        $form.Size = New-Object Drawing.Size(700, 500)
        $form.StartPosition = "CenterScreen"
        $form.AllowDrop = $true
        
        # Create log textbox
        $logBox = New-Object Windows.Forms.TextBox
        $logBox.Multiline = $true
        $logBox.ScrollBars = "Vertical"
        $logBox.Dock = "Fill"
        $logBox.Font = New-Object Drawing.Font("Consolas", 10)
        $logBox.ReadOnly = $true
        
        # Create button
        $button = New-Object Windows.Forms.Button
        $button.Text = "Select Excel File(s)"
        $button.Dock = "Bottom"
        $button.Height = 50
        $button.FlatStyle = "Flat"
        $button.Font = New-Object Drawing.Font($button.Font.FontFamily, 11, [System.Drawing.FontStyle]::Bold)
        
        # Apply theme colors
        if ($script:isDarkMode) {
            $form.BackColor = $darkBackColor
            $form.ForeColor = $darkForeColor
            $logBox.BackColor = $darkControlBackColor
            $logBox.ForeColor = $darkForeColor
            $button.BackColor = $darkControlBackColor
            $button.ForeColor = $script:accentColor
            $button.FlatAppearance.BorderColor = $script:accentColor
        } else {
            $button.ForeColor = $script:accentColor
        }
        
        # Apply dark mode to title bar (must be in Shown event)
        $form.Add_Shown({
            if ($script:isDarkMode) {
                $darkModeValue = 1
                [void][DarkMode]::DwmSetWindowAttribute($form.Handle, 20, [ref]$darkModeValue, 4)
            }
        })
        
        # Button click handler
        $button.Add_Click({
            $openFileDialog = New-Object Windows.Forms.OpenFileDialog
            $openFileDialog.Filter = "Excel files (*.xlsx;*.xls;*.xlsm)|*.xlsx;*.xls;*.xlsm"
            $openFileDialog.Multiselect = $true
            
            if ($openFileDialog.ShowDialog() -eq 'OK') {
                $button.Enabled = $false
                $logBox.Clear()
                
                foreach ($file in $openFileDialog.FileNames) {
                    Process-ExcelFile -filePath $file -logBox $logBox
                }
                
                $button.Enabled = $true
            }
        })
        
        # Drag & drop handlers
        $form.Add_DragEnter({
            if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
                $_.Effect = [Windows.Forms.DragDropEffects]::Copy
            }
        })
        
        $form.Add_DragDrop({
            $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
            $excelFiles = $files | Where-Object { $_ -match "\.(xlsx|xls|xlsm)$" }
            
            if ($excelFiles.Count -eq 0) {
                $logBox.AppendText("Please drop Excel file(s) (.xlsx, .xls, or .xlsm)`r`n")
                return
            }
            
            $button.Enabled = $false
            $logBox.Clear()
            
            foreach ($file in $excelFiles) {
                Process-ExcelFile -filePath $file -logBox $logBox
            }
            
            $button.Enabled = $true
        })
        
        # Initial instructions
        $logBox.AppendText("EXCEL TO CSV EXPORTER`r`n")
        $logBox.AppendText("====================`r`n`r`n")
        $logBox.AppendText("This tool exports all sheets from Excel files to CSV format.`r`n`r`n")
        $logBox.AppendText("For each Excel file:`r`n")
        $logBox.AppendText("  1. Creates a folder with the same name as the file`r`n")
        $logBox.AppendText("  2. Exports each sheet to a separate CSV file`r`n")
        $logBox.AppendText("  3. Sanitizes sheet names (replaces special characters)`r`n`r`n")
        $logBox.AppendText("Drag & drop Excel files here or click the button below.`r`n")
        
        # Add controls to form
        $form.Controls.Add($logBox)
        $form.Controls.Add($button)
        
        # Show the form
        [void]$form.ShowDialog()
    }
    
    TOM
    TOM --- ---
    jenom taková drobnůstka, převede XLSX (zejména s více sešity) na jednotlivá CSV a souhrnný MD
    (zejména pokud potřebujete nějakými výstupy z Excelu zpětně krmit stroj ;))
    funguje i jako zástupce bez GUI - pokud v Total Commanderu vytvoříte zástupce, rozpozná drag&drop (lze pouze jednotlivé soubory)
    pro automatické uzavření konzole (pokud nechcete vidět průběh a report) změňte cmd /k na konci sedmého řádku na cmd /c
    jo a kód vložte do textového souboru typu .cmd (je to zawrappovaný powershell)

    @@ echo off
    @@ echo Invoking a Powershell script...
    @@ setlocal
    @@ set PS_WRAPPER_ARGS=%*
    @@ set PS_WRAPPER_PATH=%~f0
    @@ if defined PS_WRAPPER_ARGS set PS_WRAPPER_ARGS=%PS_WRAPPER_ARGS:"="%
    @@ PowerShell -sta -Command Invoke-Expression $('$args=@(^&{$args} %PS_WRAPPER_ARGS%);'+[String]::Join([Environment]::NewLine,$((Get-Content '%PS_WRAPPER_PATH%') -notmatch '^^@@^|^^:^|^^cls'))) & endlocal & cmd /k
    
    Add-Type -AssemblyName System.Windows.Forms, PresentationFramework, WindowsBase
    
    Add-Type @"
    using System;
    using System.Runtime.InteropServices;
    
    public class DarkMode {
        [DllImport("dwmapi.dll")]
        public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
    }
    "@
    
    # Dark mode detection
    function Get-WindowsTheme {
        try {
            $path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize"
            $value = Get-ItemProperty -Path $path -Name "AppsUseLightTheme" -ErrorAction Stop
            return $value.AppsUseLightTheme -eq 0
        } catch {
            return $false
        }
    }
    
    # Initialize theme-specific colors
    $script:isDarkMode = Get-WindowsTheme
    $darkBackColor = [System.Drawing.Color]::FromArgb(32, 32, 32)
    $darkForeColor = [System.Drawing.Color]::FromArgb(240, 240, 240)
    $darkControlBackColor = [System.Drawing.Color]::FromArgb(45, 45, 45)
    
    # Fix: Use theme-specific accent colors for proper visibility
    $script:accentColor = if ($script:isDarkMode) { 
        [System.Drawing.Color]::FromArgb(120, 250, 174)  # Light green for dark mode
    } else { 
        [System.Drawing.Color]::FromArgb(0, 120, 50)     # Darker green for light mode
    }
    
    # Character replacement mapping (using character codes to avoid UTF-8 encoding issues)
    $script:charMap = @{
        [char]0x00E4 = 'ae'; [char]0x00F6 = 'oe'; [char]0x00FC = 'ue'; [char]0x00E9 = 'e'
        [char]0x00E8 = 'e'; [char]0x00EA = 'e'; [char]0x011B = 'e'; [char]0x00E0 = 'a'
        [char]0x00C4 = 'AE'; [char]0x00D6 = 'OE'; [char]0x00DC = 'UE'; [char]0x00C9 = 'E'
        [char]0x00C8 = 'E'; [char]0x00CA = 'E'; [char]0x011A = 'E'; [char]0x00C0 = 'A'
        [char]0x00E1 = 'a'; [char]0x010D = 'c'; [char]0x010F = 'd'; [char]0x00ED = 'i'
        [char]0x0148 = 'n'; [char]0x00F3 = 'o'; [char]0x0159 = 'r'; [char]0x0161 = 's'
        [char]0x0165 = 't'; [char]0x016F = 'u'; [char]0x00FA = 'u'; [char]0x00FD = 'y'
        [char]0x017E = 'z'; [char]0x0142 = 'l'; [char]0x0111 = 'd'
        [char]0x00C1 = 'A'; [char]0x010C = 'C'; [char]0x010E = 'D'; [char]0x00CD = 'I'
        [char]0x0147 = 'N'; [char]0x00D3 = 'O'; [char]0x0158 = 'R'; [char]0x0160 = 'S'
        [char]0x0164 = 'T'; [char]0x016E = 'U'; [char]0x00DA = 'U'; [char]0x00DD = 'Y'
        [char]0x017D = 'Z'; [char]0x0141 = 'L'; [char]0x0110 = 'D'
        [char]0x00DF = 'ss'; ',' = '_'; ' ' = '_'; '.' = '_'; '!' = '_'; [char]0x00A7 = '_'
        "'" = '_'; [char]0x00B4 = '_'; [char]0x02C7 = '_'; ';' = '_'; '(' = '_'; ')' = '_'; '-' = '_'
    }
    
    # Function to sanitize sheet names
    function Sanitize-SheetName {
        param([string]$name)
        
        $result = $name
        foreach ($key in $script:charMap.Keys) {
            $result = $result -replace [regex]::Escape($key), $script:charMap[$key]
        }
        return $result
    }
    
    # Function to process a single Excel file
    function Process-ExcelFile {
        param(
            [string]$filePath,
            [System.Windows.Forms.TextBox]$logBox = $null
        )
        
        $excel = $null
        $workbook = $null
        
        try {
            # Validate file
            if (-not (Test-Path $filePath)) {
                $msg = "ERROR: File not found: $filePath"
                if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
                return
            }
            
            if ($filePath -notmatch "\.(xlsx|xlsm|xls)$") {
                $msg = "ERROR: Not an Excel file: $filePath"
                if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
                return
            }
            
            $msg = "Processing: $filePath"
            if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
            
            # Create output folder
            $fileInfo = Get-Item $filePath
            $folderName = [System.IO.Path]::GetFileNameWithoutExtension($fileInfo.Name)
            $outputFolder = Join-Path $fileInfo.DirectoryName $folderName
            
            if (-not (Test-Path $outputFolder)) {
                [void](New-Item -ItemType Directory -Path $outputFolder -Force)
                $msg = "Created folder: $outputFolder"
                if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
            }
            
            # Open Excel
            $excel = New-Object -ComObject Excel.Application
            $excel.Visible = $false
            $excel.DisplayAlerts = $false
            $excel.ScreenUpdating = $false
            
            $workbook = $excel.Workbooks.Open($filePath)
            $sheetCount = $workbook.Sheets.Count
            
            $msg = "Found $sheetCount sheet(s)"
            if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
            
            # Export each sheet and collect info for markdown
            $sheetInfo = @()
            for ($i = 1; $i -le $sheetCount; $i++) {
                $sheet = $workbook.Sheets.Item($i)
                $sheetName = $sheet.Name
                $sanitizedName = Sanitize-SheetName $sheetName
                $csvPath = Join-Path $outputFolder "$sanitizedName.csv"
                
                $msg = "  Exporting sheet '$sheetName' -> '$sanitizedName.csv'"
                if ($logBox) { 
                    $logBox.AppendText("$msg`r`n")
                    [System.Windows.Forms.Application]::DoEvents()
                } else { 
                    Write-Host $msg 
                }
                
                # Save as CSV (Excel format 6 = CSV)
                $sheet.SaveAs($csvPath, 6)
                
                # Store info for markdown
                $sheetInfo += [PSCustomObject]@{
                    OriginalName = $sheetName
                    SanitizedName = $sanitizedName
                    CsvPath = $csvPath
                }
                
                # Release sheet COM object
                [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($sheet)
            }
            
            # Create combined markdown file
            $msg = "`r`n  Creating combined markdown file..."
            if ($logBox) { 
                $logBox.AppendText("$msg`r`n")
                [System.Windows.Forms.Application]::DoEvents()
            } else { 
                Write-Host $msg 
            }
            
            $markdownPath = Join-Path $outputFolder "$folderName.md"
            $markdownContent = ""
            
            foreach ($info in $sheetInfo) {
                $markdownContent += "# $($info.OriginalName)`r`n"
                if (Test-Path $info.CsvPath) {
                    $csvContent = Get-Content -Path $info.CsvPath -Raw -Encoding UTF8
                    $markdownContent += $csvContent.TrimEnd() + "`r`n`r`n"
                }
            }
            
            $markdownContent | Set-Content -Path $markdownPath -Encoding UTF8
            
            $msg = "`r`nSuccess! Exported $sheetCount sheet(s) to: $outputFolder`r`n"
            $msg += "  - Individual CSV files: $sheetCount`r`n"
            $msg += "  - Combined markdown: $folderName.md`r`n"
            if ($logBox) { $logBox.AppendText("$msg") } else { Write-Host $msg }
            
        } catch {
            $msg = "ERROR: $_"
            if ($logBox) { $logBox.AppendText("$msg`r`n") } else { Write-Host $msg }
        } finally {
            # Cleanup COM objects (critical!)
            if ($workbook -ne $null) {
                $workbook.Close($false)
                [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($workbook)
            }
            
            if ($excel -ne $null) {
                $excel.Quit()
                [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel)
            }
            
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
            Start-Sleep -Milliseconds 500
        }
    }
    
    # Main logic: Check if file was drag-dropped
    if ($args.Count -gt 0 -and $args[0]) {
        # Silent mode - no GUI
        $filePath = $args[0]
        Process-ExcelFile -filePath $filePath
        
    } else {
        # GUI mode - no file provided
        
        # Create main form
        $form = New-Object Windows.Forms.Form
        $form.Text = "Excel to CSV Exporter"
        $form.Size = New-Object Drawing.Size(700, 500)
        $form.StartPosition = "CenterScreen"
        $form.AllowDrop = $true
        
        # Create log textbox
        $logBox = New-Object Windows.Forms.TextBox
        $logBox.Multiline = $true
        $logBox.ScrollBars = "Vertical"
        $logBox.Dock = "Fill"
        $logBox.Font = New-Object Drawing.Font("Consolas", 10)
        $logBox.ReadOnly = $true
        
        # Create button
        $button = New-Object Windows.Forms.Button
        $button.Text = "Select Excel File(s)"
        $button.Dock = "Bottom"
        $button.Height = 50
        $button.FlatStyle = "Flat"
        $button.Font = New-Object Drawing.Font($button.Font.FontFamily, 11, [System.Drawing.FontStyle]::Bold)
        
        # Apply theme colors
        if ($script:isDarkMode) {
            $form.BackColor = $darkBackColor
            $form.ForeColor = $darkForeColor
            $logBox.BackColor = $darkControlBackColor
            $logBox.ForeColor = $darkForeColor
            $button.BackColor = $darkControlBackColor
            $button.ForeColor = $script:accentColor
            $button.FlatAppearance.BorderColor = $script:accentColor
        } else {
            $button.ForeColor = $script:accentColor
        }
        
        # Apply dark mode to title bar (must be in Shown event)
        $form.Add_Shown({
            if ($script:isDarkMode) {
                $darkModeValue = 1
                [void][DarkMode]::DwmSetWindowAttribute($form.Handle, 20, [ref]$darkModeValue, 4)
            }
        })
        
        # Button click handler
        $button.Add_Click({
            $openFileDialog = New-Object Windows.Forms.OpenFileDialog
            $openFileDialog.Filter = "Excel files (*.xlsx;*.xls;*.xlsm)|*.xlsx;*.xls;*.xlsm"
            $openFileDialog.Multiselect = $true
            
            if ($openFileDialog.ShowDialog() -eq 'OK') {
                $button.Enabled = $false
                $logBox.Clear()
                
                foreach ($file in $openFileDialog.FileNames) {
                    Process-ExcelFile -filePath $file -logBox $logBox
                }
                
                $button.Enabled = $true
            }
        })
        
        # Drag & drop handlers
        $form.Add_DragEnter({
            if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
                $_.Effect = [Windows.Forms.DragDropEffects]::Copy
            }
        })
        
        $form.Add_DragDrop({
            $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
            $excelFiles = $files | Where-Object { $_ -match "\.(xlsx|xls|xlsm)$" }
            
            if ($excelFiles.Count -eq 0) {
                $logBox.AppendText("Please drop Excel file(s) (.xlsx, .xls, or .xlsm)`r`n")
                return
            }
            
            $button.Enabled = $false
            $logBox.Clear()
            
            foreach ($file in $excelFiles) {
                Process-ExcelFile -filePath $file -logBox $logBox
            }
            
            $button.Enabled = $true
        })
        
        # Initial instructions
        $logBox.AppendText("EXCEL TO CSV EXPORTER`r`n")
        $logBox.AppendText("====================`r`n`r`n")
        $logBox.AppendText("This tool exports all sheets from Excel files to CSV format + combined MD.`r`n`r`n")
        $logBox.AppendText("For each Excel file it:`r`n")
        $logBox.AppendText("  1. Creates a folder with the same name as the file`r`n")
        $logBox.AppendText("  2. Exports each sheet to a separate CSV file`r`n")
        $logBox.AppendText("  3. Exports each sheet to a combined MD file`r`n")
        $logBox.AppendText("  4. Sanitizes sheet names (replaces special characters)`r`n`r`n")
        $logBox.AppendText("Drag & drop Excel files here or click the button below.`r`n")
        
        # Add controls to form
        $form.Controls.Add($logBox)
        $form.Controls.Add($button)
        
        # Show the form
        [void]$form.ShowDialog()
    }
    HNZ
    HNZ --- ---
    glean (chatgpt 5)
    Kliknutím sem můžete změnit nastavení reklam