první commit

This commit is contained in:
Josef Marek 2025-04-09 15:19:58 +02:00
commit 641e9bc2e6
13 changed files with 545 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.vs
bin
obj

9
App.xaml Normal file
View File

@ -0,0 +1,9 @@
<Application x:Class="Slučování_rozpisek.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Slučování_rozpisek"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

14
App.xaml.cs Normal file
View File

@ -0,0 +1,14 @@
using System.Configuration;
using System.Data;
using System.Windows;
namespace Slučování_rozpisek
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

10
AssemblyInfo.cs Normal file
View File

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

59
MainWindow.xaml Normal file
View File

@ -0,0 +1,59 @@
<Window x:Name="HlavniOkno" x:Class="SlucovaniRozpisek.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SlucovaniRozpisek"
mc:Ignorable="d"
Title="Slučování rozpisek" SizeToContent="WidthAndHeight" Background="WhiteSmoke" Icon=".\icopdf.ico"
WindowStartupLocation="Manual" Left="200" Top="200"
>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="25"/>
<RowDefinition Height="20"/>
<RowDefinition Height="25"/>
<RowDefinition Height="20"/>
<RowDefinition Height="25"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="Cesta ke složce s přílohami:" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" FontSize="14"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal">
<TextBox Name="cestaPrilohyBox" Margin="0, 0, 5, 0" Width="360" VerticalContentAlignment="Center" FontSize="14"
Text="{Binding CestaPrilohy, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Name="cestaPrilohyButton" Content="&#xED25;" Foreground="DarkOrange" FontFamily="Segoe MDL2 Assets" FontSize="15" Width="40" Click="btnCestaPrilohyClick"/>
</StackPanel>
<StackPanel Grid.Row="2" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="Cesta ke složce s rozpiskami:" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" FontSize="14"/>
</StackPanel>
<StackPanel Grid.Row="3" Grid.Column="0" Orientation="Horizontal">
<TextBox Name="cestaRozpiskyBox" Margin="0, 0, 5, 0" Width="360" VerticalContentAlignment="Center" FontSize="14"
Text="{Binding CestaRozpisky, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Name="cestaRozpiskyButton" Content="&#xED25;" Foreground="DarkOrange" FontFamily="Segoe MDL2 Assets" FontSize="15" Width="40" Click="btnCestaRozpiskyClick"/>
</StackPanel>
<StackPanel Grid.Row="4" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="Cesta k výstupní složce:" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" FontSize="14"/>
</StackPanel>
<StackPanel Grid.Row="5" Grid.Column="0" Orientation="Horizontal">
<TextBox Name="cestaVystupBox" Margin="0, 0, 5, 0" Width="360" VerticalContentAlignment="Center" FontSize="14"
Text="{Binding CestaVystup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Name="cestaVystupButton" Content="&#xED25;" Foreground="DarkOrange" FontFamily="Segoe MDL2 Assets" FontSize="15" Width="40" Click="btnCestaVystupClick"/>
</StackPanel>
<StackPanel Grid.Row="6" Grid.Column="0" Orientation="Horizontal">
<Button Name="slucRozpisky" Content="Sloučit rozpisky" Width="180" Margin="10" Click="btnSlucRozpiskyClick" Foreground="Red"/>
<Button Name="Napoveda" Content="Nápověda" Width="180" Margin="10" Click="btnNapoveda"/>
</StackPanel>
</Grid>
</Window>

204
MainWindow.xaml.cs Normal file
View File

@ -0,0 +1,204 @@
using Microsoft.Win32;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows;
namespace SlucovaniRozpisek
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainViewModel ViewModel { get; set; }
public MainWindow()
{
InitializeComponent();
ViewModel = new MainViewModel();
this.DataContext = ViewModel;
// jen pro testování
#if (DEBUG)
ViewModel.CestaPrilohy = "d:\\Přesunuté\\.NET\\Csharp_výuka\\SlucovaniPDF\\Přílohy";
ViewModel.CestaRozpisky = "d:\\Přesunuté\\.NET\\Csharp_výuka\\SlucovaniPDF\\Rozpisky";
ViewModel.CestaVystup = "d:\\Přesunuté\\.NET\\Csharp_výuka\\SlucovaniPDF\\Výstup";
#endif
}
private void btnCestaPrilohyClick(object sender, RoutedEventArgs e)
{
OpenFolderDialog folderDialog = new OpenFolderDialog();
folderDialog.Title = "Vyberte složku s přílohami";
if (folderDialog.ShowDialog() == true)
{
ViewModel.CestaPrilohy = folderDialog.FolderName;
}
}
private void btnCestaRozpiskyClick(object sender, RoutedEventArgs e)
{
OpenFolderDialog folderDialog = new OpenFolderDialog();
folderDialog.Title = "Vyberte složku s rozpiskami";
if (folderDialog.ShowDialog() == true)
{
ViewModel.CestaRozpisky = folderDialog.FolderName;
}
}
private void btnCestaVystupClick(object sender, RoutedEventArgs e)
{
OpenFolderDialog folderDialog = new OpenFolderDialog();
folderDialog.Title = "Vyberte výstupní složku";
if (folderDialog.ShowDialog() == true)
{
ViewModel.CestaVystup = folderDialog.FolderName;
}
}
private void btnSlucRozpiskyClick(object sender, RoutedEventArgs e)
{
if (!Directory.Exists(ViewModel.CestaPrilohy))
{
MessageBox.Show("Složka s přílohami neexistuje,\nzadejte existující cestu.", "Kontrola složky",
MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
if (!Directory.Exists(ViewModel.CestaRozpisky))
{
MessageBox.Show("Složka s rozpiskami neexistuje,\nzadejte existující cestu.", "Kontrola složky",
MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
if (!Directory.Exists(ViewModel.CestaVystup))
{
MessageBox.Show("Výstupní složka neexistuje,\nzadejte existující cestu.", "Kontrola složky",
MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
if (!PomocneMetody. ObsahujePdf(ViewModel.CestaPrilohy))
{
MessageBox.Show("Složka s přílohami neobsahuje žádná PDF,\nkterá by se mohla dát sloučit.", "Kontrola existence PDF",
MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
List<string> lstPrilohy = PomocneMetody.NactiPdfNazvyBezKoncovky(ViewModel.CestaPrilohy);
List<string> lstRozpisky = PomocneMetody.NactiPdfNazvyBezKoncovky(ViewModel.CestaRozpisky);
PdfRozdelovac pdfka = new PdfRozdelovac(lstPrilohy, lstRozpisky);
if (MessageBox.Show(pdfka.Zprava, "Přejete si pokračovat?",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
{
return;
}
string cestaPrilohysLomitkem = PomocneMetody.NormalizujCestu(ViewModel.CestaPrilohy);
string cestaRozpiskysLomitkem = PomocneMetody.NormalizujCestu(ViewModel.CestaRozpisky);
string cestaVystupsLomitkem = PomocneMetody.NormalizujCestu(ViewModel.CestaVystup);
foreach (string pdf in pdfka.NeparovePrilohy)
{
PomocneMetody.KopirujSoubor(cestaPrilohysLomitkem + pdf + ".pdf", cestaVystupsLomitkem + pdf + ".pdf", true);
}
foreach (string pdf in pdfka.NeparoveRozpisky)
{
PomocneMetody.KopirujSoubor(cestaRozpiskysLomitkem + pdf + ".pdf", cestaVystupsLomitkem + pdf + ".pdf", true);
}
foreach (string pdf in pdfka.ParovePrilohy)
{
PomocneMetody.SloucitPdf(cestaPrilohysLomitkem + pdf + ".pdf", cestaRozpiskysLomitkem + pdf + "_rozpiska.pdf", cestaVystupsLomitkem + pdf + ".pdf", true);
}
MessageBox.Show("Rozpisky byly úspěšně sloučeny.", "Hotovo",
MessageBoxButton.OK, MessageBoxImage.Information);
}
private void btnNapoveda(object sender, RoutedEventArgs e)
{
try
{
string helpFileName = "help.pdf"; // Název souboru s nápovědou
string helpFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, helpFileName);
if (File.Exists(helpFilePath))
{
Process.Start(new ProcessStartInfo(helpFilePath) { UseShellExecute = true });
}
else
{
MessageBox.Show("Soubor s nápovědou nebyl nalezen!", "Chyba", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
MessageBox.Show($"Chyba při otevírání nápovědy: {ex.Message}", "Chyba", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
public class MainViewModel : INotifyPropertyChanged
{
private string _cestaPrilohy = string.Empty; // inicializace
public string CestaPrilohy
{
get { return _cestaPrilohy; }
set
{
if (_cestaPrilohy != value)
{
_cestaPrilohy = value;
OnPropertyChanged(nameof(CestaPrilohy));
}
}
}
private string _cestaRozpisky = string.Empty; // inicializace
public string CestaRozpisky
{
get { return _cestaRozpisky; }
set
{
if (_cestaRozpisky != value)
{
_cestaRozpisky = value;
OnPropertyChanged(nameof(CestaRozpisky));
}
}
}
private string _cestaVystup = string.Empty; // inicializace
public string CestaVystup
{
get { return _cestaVystup; }
set
{
if (_cestaVystup != value)
{
_cestaVystup = value;
OnPropertyChanged(nameof(CestaVystup));
}
}
}
public event PropertyChangedEventHandler? PropertyChanged; // nullable event
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

40
PdfRozdelovac.cs Normal file
View File

@ -0,0 +1,40 @@
namespace SlucovaniRozpisek
{
public class PdfRozdelovac
{
public List<string> ParovePrilohy { get; private set; }
public List<string> NeparovePrilohy { get; private set; }
public List<string> NeparoveRozpisky { get; private set; }
public string Zprava { get; private set; }
public PdfRozdelovac(List<string> lstPrilohy, List<string> lstRozpisky)
{
ParovePrilohy = new List<string>();
NeparovePrilohy = new List<string>();
NeparoveRozpisky = new List<string>(lstRozpisky);
Zprava = string.Empty;
RozdelPdfSoubor(lstPrilohy, lstRozpisky);
}
private void RozdelPdfSoubor(List<string> lstPrilohy, List<string> lstRozpisky)
{
foreach (var priloha in lstPrilohy)
{
string rozpiska = priloha + "_rozpiska";
if (lstRozpisky.Contains(rozpiska))
{
ParovePrilohy.Add(priloha);
NeparoveRozpisky.Remove(rozpiska);
}
else
{
NeparovePrilohy.Add(priloha);
}
}
NeparoveRozpisky = NeparoveRozpisky.Where(r => !r.EndsWith("_rozpiska")).ToList();
Zprava = $"Počet párových příloh: {ParovePrilohy.Count}\nPočet nepárových příloh: {NeparovePrilohy.Count}\nPočet nepárových rozpisek: {NeparoveRozpisky.Count}";
}
}
}

138
PomocneMetody.cs Normal file
View File

@ -0,0 +1,138 @@
using System.IO;
using System.Windows;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using PdfSharp.Drawing;
public static class PomocneMetody
{
public static bool ObsahujePdf(string cestaSlozky)
{
if (string.IsNullOrWhiteSpace(cestaSlozky) || !Directory.Exists(cestaSlozky))
{
throw new ArgumentException("Neplatná cesta ke složce.", nameof(cestaSlozky));
}
return Directory.GetFiles(cestaSlozky, "*.pdf").Length > 0;
}
public static List<string> NactiPdfZeSlozky(string cestaSlozky)
{
if (string.IsNullOrWhiteSpace(cestaSlozky) || !Directory.Exists(cestaSlozky))
{
throw new ArgumentException("Neplatná cesta ke složce.", nameof(cestaSlozky));
}
return Directory.GetFiles(cestaSlozky, "*.pdf")
.Select(f => Path.GetFileName(f) ?? string.Empty)
.Where(f => !string.IsNullOrEmpty(f))
.ToList();
}
public static List<string> NactiPdfNazvyBezKoncovky(string cestaSlozky)
{
if (string.IsNullOrWhiteSpace(cestaSlozky) || !Directory.Exists(cestaSlozky))
{
throw new ArgumentException("Neplatná cesta ke složce.", nameof(cestaSlozky));
}
return Directory.GetFiles(cestaSlozky, "*.pdf")
.Select(f => Path.GetFileNameWithoutExtension(f) ?? string.Empty)
.Where(f => !string.IsNullOrEmpty(f))
.ToList();
}
public static string NormalizujCestu(string cesta)
{
if (string.IsNullOrWhiteSpace(cesta))
{
throw new ArgumentException("Neplatná cesta ke složce.", nameof(cesta));
}
return cesta.EndsWith(Path.DirectorySeparatorChar) ? cesta : cesta + Path.DirectorySeparatorChar;
}
public static void KopirujSoubor(string zdrojovySoubor, string cilovySoubor, bool prepsatExistujici)
{
if (string.IsNullOrWhiteSpace(zdrojovySoubor) || string.IsNullOrWhiteSpace(cilovySoubor))
{
throw new ArgumentException("Neplatná cesta ke zdrojovému nebo cílovému souboru.");
}
if (!File.Exists(zdrojovySoubor))
{
throw new FileNotFoundException("Zdrojový soubor neexistuje.", zdrojovySoubor);
}
try
{
if (File.Exists(cilovySoubor))
{
if (prepsatExistujici)
{
File.Copy(zdrojovySoubor, cilovySoubor, true);
}
}
else
{
File.Copy(zdrojovySoubor, cilovySoubor);
}
}
catch (IOException ex)
{
MessageBox.Show($"Chyba při kopírování souboru {zdrojovySoubor}: {ex.Message}", "Chyba", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public static void SloucitPdf(string pdfJedna, string pdfDva, string vystupniPdf, bool prepsatExistujici)
{
if (!File.Exists(pdfJedna) || !File.Exists(pdfDva))
{
throw new FileNotFoundException("Jeden nebo oba vstupní PDF soubory neexistují.");
}
if (File.Exists(vystupniPdf) && !prepsatExistujici)
{
throw new IOException("Výstupní PDF již existuje a přepsání není povoleno.");
}
try
{
using (PdfDocument docJedna = PdfReader.Open(pdfJedna, PdfDocumentOpenMode.Modify))
{
var strankaJedna = docJedna.Pages[0];
double sirkaJedna = strankaJedna.Width.Value;
double vyskaJedna = strankaJedna.Height.Value;
using (PdfDocument docDva = PdfReader.Open(pdfDva, PdfDocumentOpenMode.Import))
{
if (docDva.PageCount > 0)
{
XPdfForm form = XPdfForm.FromFile(pdfDva);
form.PageNumber = 1;
var strankaDva = docDva.Pages[0];
double sirkaDva = strankaDva.Width.Value;
double vyskaDva = strankaDva.Height.Value;
XRect pozice = new XRect(sirkaJedna - sirkaDva, vyskaJedna - vyskaDva, sirkaDva, vyskaDva);
using (XGraphics gfx = XGraphics.FromPdfPage(strankaJedna, XGraphicsPdfPageOptions.Prepend))
{
gfx.DrawImage(form, pozice);
}
docJedna.Save(vystupniPdf);
}
else
{
MessageBox.Show("Druhý PDF dokument neobsahuje žádné stránky.", "Chyba", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
}
}
catch (IOException ex)
{
MessageBox.Show($"Chyba při práci s PDF soubory: {ex.Message}", "Chyba", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}

43
SlucovaniRozpisek.csproj Normal file
View File

@ -0,0 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<RootNamespace>SlucovaniRozpisek</RootNamespace>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<UseWindowsForms>False</UseWindowsForms>
<ApplicationIcon>icopdf.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<None Remove="icopdf.ico" />
</ItemGroup>
<ItemGroup>
<Content Include="icopdf.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="PDFsharp" Version="6.1.1">
<PrivateAssets></PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Update="help.pdf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Page Update="MainWindow.xaml">
<Generator>XamlIntelliSenseFileGenerator</Generator>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Page>
</ItemGroup>
</Project>

25
Slučování rozpisek.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlucovaniRozpisek", "SlucovaniRozpisek.csproj", "{275156B7-2F2D-4B71-99F8-8AB1A86BEF38}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{275156B7-2F2D-4B71-99F8-8AB1A86BEF38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{275156B7-2F2D-4B71-99F8-8AB1A86BEF38}.Debug|Any CPU.Build.0 = Debug|Any CPU
{275156B7-2F2D-4B71-99F8-8AB1A86BEF38}.Release|Any CPU.ActiveCfg = Release|Any CPU
{275156B7-2F2D-4B71-99F8-8AB1A86BEF38}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4539D8DF-ECA2-4E4E-A93F-51090E61F4B6}
EndGlobalSection
EndGlobal

BIN
help.docx Normal file

Binary file not shown.

BIN
help.pdf Normal file

Binary file not shown.

BIN
icopdf.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB