при создании файла из .magnete в первые два столбца вместе с датой заносится время, так быть не должно, там должна быть дата
также столбец computedtime неправильно рассчитывается ((A-18-((B-C)*86400))/24/60/60), где A-первый столбец из файла, B-первый столбец дата которую ввел пользователь, C- второй столбец 06.01.1980
при этом получается что в формуле есть переменные в виде даты, нужно считать как в экселе там у даты есть десятичный аналог, также после расчета этот столбец должен быть в формате времени

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace TxtProcessorApp
{
    public partial class MagneteWindow : Window
    {
        private Dictionary<string, List<string[]>> magneteFileData;
        private DataTable combinedMagneteDataTable = null;

        public MagneteWindow(Dictionary<string, List<string[]>> loadedMagneteData)
        {
            InitializeComponent();
            magneteFileData = loadedMagneteData;
            PopulateMagneteTabControl();
        }

        private void PopulateMagneteTabControl()
        {
            MagneteTabControl.Items.Clear();

            foreach (var kvp in magneteFileData)
            {
                string fileName = kvp.Key;
                List<string[]> data = kvp.Value;

                DataGrid dataGrid = new DataGrid
                {
                    AutoGenerateColumns = true,
                    IsReadOnly = true
                };

                DataTable dataTable = ConvertToDataTable(data);
                dataGrid.ItemsSource = dataTable.DefaultView;

                TabItem tabItem = new TabItem
                {
                    Header = fileName,
                    Content = dataGrid
                };

                MagneteTabControl.Items.Add(tabItem);
            }
        }

        private DataTable ConvertToDataTable(List<string[]> data)
        {
            DataTable dt = new DataTable();

            if (data == null || data.Count == 0)
                return dt;

            // Предполагаем, что .magnete файлы имеют как минимум 5 столбцов
            dt.Columns.Add("Stan", typeof(string));
            dt.Columns.Add("Zeit", typeof(string));
            dt.Columns.Add("Noise", typeof(string));
            dt.Columns.Add("Time", typeof(string));
            dt.Columns.Add("Time UTC", typeof(string));

            foreach (var row in data)
            {
                DataRow dr = dt.NewRow();
                dr["Stan"] = row.Length > 0 ? row[0] : string.Empty;
                dr["Zeit"] = row.Length > 1 ? row[1] : string.Empty;
                dr["Noise"] = row.Length > 2 ? row[2] : string.Empty;
                dr["Time"] = row.Length > 3 ? row[3] : string.Empty;
                dr["Time UTC"] = row.Length > 4 ? row[4] : string.Empty;
                dt.Rows.Add(dr);
            }

            return dt;
        }

        // Обработчик кнопки Объединить .magnete файлы
        private void CombineMagneteFiles_Click(object sender, RoutedEventArgs e)
        {
            if (!magneteFileData.Any())
            {
                MessageBox.Show("Нет загруженных .magnete файлов для объединения.", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            if (!UserDatePicker.SelectedDate.HasValue)
            {
                MessageBox.Show("Пожалуйста, выберите дату.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            DateTime userDate = UserDatePicker.SelectedDate.Value.Date; // Убираем компонент времени
            DateTime fixedDate = DateTime.ParseExact("06.01.1980", "dd.MM.yyyy", CultureInfo.InvariantCulture);

            // Объединяем все данные из .magnete файлов
            combinedMagneteDataTable = new DataTable();

            // Определение столбцов согласно требованиям
            combinedMagneteDataTable.Columns.Add("Дата", typeof(DateTime));
            combinedMagneteDataTable.Columns.Add("ФиксированнаяДата", typeof(DateTime));
            combinedMagneteDataTable.Columns.Add("Column3", typeof(string)); // Первый столбец из файла magnete (Stan)
            combinedMagneteDataTable.Columns.Add("ComputedTime", typeof(double)); // Вычисляемое значение
            combinedMagneteDataTable.Columns.Add("Column5", typeof(string)); // Третий столбец из файла magnete (Noise)
            combinedMagneteDataTable.Columns.Add("Column2", typeof(string)); // Второй столбец из файла magnete (Zeit)
            combinedMagneteDataTable.Columns.Add("Zero1", typeof(int));
            combinedMagneteDataTable.Columns.Add("Zero2", typeof(int));
            combinedMagneteDataTable.Columns.Add("SequentialNumber1", typeof(int));
            combinedMagneteDataTable.Columns.Add("Column10", typeof(string)); // Четвёртый столбец из файла magnete (Time)
            combinedMagneteDataTable.Columns.Add("SequentialNumber2", typeof(int));
            combinedMagneteDataTable.Columns.Add("Column12", typeof(string)); // Пятый столбец из файла magnete (Time UTC)

            int sequentialNumber = 1;

            double dateDifferenceSeconds = (userDate - fixedDate).TotalSeconds;
            double dateDifferenceDays = (userDate - fixedDate).TotalDays;

            foreach (var file in magneteFileData.Values)
            {
                foreach (var row in file)
                {
                    if (row.Length < 5)
                        continue; // Убедитесь, что есть минимум 5 столбцов

                    // Создание новой строки для объединённой таблицы
                    DataRow newRow = combinedMagneteDataTable.NewRow();

                    // Столбец 1: Дата (из выбранной пользователем даты)
                    newRow["Дата"] = userDate;

                    // Столбец 2: Постоянная дата 06.01.1980
                    newRow["ФиксированнаяДата"] = fixedDate;

                    // Столбец 3: Первый столбец из файла magnete (Stan)
                    string stanValue = row[0];
                    newRow["Column3"] = stanValue;

                    // Столбец 4: Вычисляемое значение по формуле: (Time - 18 - ((dateDifferenceDays) * 86400)) / 86400
                    // Где:
                    // Time = значение из столбца "Time" (строка 4)
                    // dateDifferenceDays = (userDate - fixedDate).TotalDays
                    if (double.TryParse(row[3], NumberStyles.Any, CultureInfo.InvariantCulture, out double time))
                    {
                        double computedValue = (time - 18 - (dateDifferenceDays * 86400)) / 86400.0;
                        newRow["ComputedTime"] = computedValue;
                    }
                    else
                    {
                        newRow["ComputedTime"] = 0.0;
                    }

                    // Столбец 5: Третий столбец из файла magnete (Noise)
                    newRow["Column5"] = row[2];

                    // Столбец 6: Второй столбец из файла magnete (Zeit)
                    newRow["Column2"] = row[1];

                    // Столбцы 7 и 8: 0
                    newRow["Zero1"] = 0;
                    newRow["Zero2"] = 0;

                    // Столбец 9: Номер по порядку
                    newRow["SequentialNumber1"] = sequentialNumber;

                    // Столбец 10: Четвёртый столбец из файла magnete (Time)
                    newRow["Column10"] = row[3];

                    // Столбец 11: Номер по порядку
                    newRow["SequentialNumber2"] = sequentialNumber;

                    // Столбец 12: Пятый столбец из файла magnete (Time UTC)
                    newRow["Column12"] = row[4];

                    combinedMagneteDataTable.Rows.Add(newRow);
                    sequentialNumber++;
                }
            }

            // Активируем кнопку редактирования и экспорта
            EditExportMagneteButton.IsEnabled = true;

            MessageBox.Show($"Файлы .magnete успешно объединены. Объединено строк: {combinedMagneteDataTable.Rows.Count}", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        // Обработчик кнопки Редактировать и Экспортировать для .magnete
        private void EditAndExportMagnete_Click(object sender, RoutedEventArgs e)
        {
            if (combinedMagneteDataTable == null)
            {
                MessageBox.Show("Нет объединённых данных для редактирования.", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            // Создаём и открываем окно редактирования
            EditWindow editWindow = new EditWindow(combinedMagneteDataTable);
            editWindow.Owner = this;
            editWindow.ShowDialog();
        }
    }
}

<Window x:Class="TxtProcessorApp.MagneteWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TxtProcessorApp"
        Title=".magnete Файлы" Height="700" Width="1000">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- Панель для выбора даты -->
        <StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Top">
            <TextBlock Text="Выберите дату:" VerticalAlignment="Center" Margin="0,0,10,0"/>
            <DatePicker x:Name="UserDatePicker" Width="150" SelectedDate="{Binding SelectedDate}" />
        </StackPanel>

        <!-- TabControl для отображения .magnete файлов -->
        <TabControl x:Name="MagneteTabControl" Grid.Row="1" Margin="0,10,0,10"/>

        <!-- Кнопки объединения файлов и редактирования -->
        <StackPanel Grid.Row="2" Orientation="Horizontal">
            <Button Content="Объединить .magnete файлы" Width="200" Height="30" Click="CombineMagneteFiles_Click"/>
            <Button Content="Редактировать и Экспортировать" Width="200" Height="30" Margin="10,0,0,0" Click="EditAndExportMagnete_Click" IsEnabled="False" x:Name="EditExportMagneteButton"/>
        </StackPanel>
    </Grid>
</Window>

using System.Windows;

namespace TxtProcessorApp
{
    /// <summary>
    /// Логика взаимодействия для InputDialog.xaml
    /// </summary>
    public partial class InputDialog : Window
    {
        public string ResponseText { get; private set; }

        public InputDialog(string question, string defaultAnswer = "")
        {
            InitializeComponent();
            PromptTextBlock.Text = question;
            ResponseTextBox.Text = defaultAnswer;
            ResponseTextBox.SelectAll();
            ResponseTextBox.Focus();
        }

        private void OK_Click(object sender, RoutedEventArgs e)
        {
            ResponseText = ResponseTextBox.Text;
            DialogResult = true;
        }
    }
}

using Microsoft.Win32;
using System;
using System.Data;
using System.Linq;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace TxtProcessorApp
{
    /// <summary>
    /// Логика взаимодействия для EditWindow.xaml
    /// </summary>
    public partial class EditWindow : Window
    {
        private DataTable _dataTable;

        public EditWindow(DataTable dataTable)
        {
            InitializeComponent();
            _dataTable = dataTable;
            EditDataGrid.ItemsSource = _dataTable.DefaultView;

            // Разрешаем добавление и удаление строк через интерфейс DataGrid
            EditDataGrid.CanUserAddRows = true;
            EditDataGrid.CanUserDeleteRows = true;
        }

        #region Вставка строк и столбцов

        // Вставка строки выше выбранной
        private void InsertRowAbove_Click(object sender, RoutedEventArgs e)
        {
            int rowIndex = GetSelectedRowIndex();
            if (rowIndex != -1)
            {
                _dataTable.Rows.InsertAt(_dataTable.NewRow(), rowIndex);
            }
            else
            {
                // Если ничего не выбрано, вставляем в конец
                _dataTable.Rows.Add(_dataTable.NewRow());
            }

            RefreshDataGrid();
        }

        // Вставка строки ниже выбранной
        private void InsertRowBelow_Click(object sender, RoutedEventArgs e)
        {
            int rowIndex = GetSelectedRowIndex();
            if (rowIndex != -1)
            {
                _dataTable.Rows.InsertAt(_dataTable.NewRow(), rowIndex + 1);
            }
            else
            {
                // Если ничего не выбрано, вставляем в конец
                _dataTable.Rows.Add(_dataTable.NewRow());
            }

            RefreshDataGrid();
        }

        // Вставка столбца слева от выбранного
        private void InsertColumnLeft_Click(object sender, RoutedEventArgs e)
        {
            int columnIndex = GetSelectedColumnIndex();
            InsertNewColumn(columnIndex, "NewColumn");
            RefreshDataGrid();
        }

        // Вставка столбца справа от выбранного
        private void InsertColumnRight_Click(object sender, RoutedEventArgs e)
        {
            int columnIndex = GetSelectedColumnIndex();
            InsertNewColumn(columnIndex + 1, "NewColumn");
            RefreshDataGrid();
        }

        // Добавление нового столбца в указанное место
        private void InsertNewColumn(int index, string defaultName)
        {
            // Предлагаем пользователю ввести имя нового столбца
            InputDialog inputDialog = new InputDialog("Введите имя нового столбца:", defaultName);
            if (inputDialog.ShowDialog() == true)
            {
                string columnName = inputDialog.ResponseText.Trim();
                if (string.IsNullOrEmpty(columnName))
                {
                    MessageBox.Show("Имя столбца не может быть пустым.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                // Проверяем, нет ли уже столбца с таким именем
                if (_dataTable.Columns.Contains(columnName))
                {
                    MessageBox.Show("Столбец с таким именем уже существует.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                // Создаём новый столбец
                DataColumn newColumn = new DataColumn(columnName, typeof(string));

                // Вставляем столбец в нужное место
                _dataTable.Columns.Add(newColumn);
                newColumn.SetOrdinal(Math.Min(index, _dataTable.Columns.Count - 1));

                // Устанавливаем значение по умолчанию для существующих строк
                foreach (DataRow row in _dataTable.Rows)
                {
                    row[newColumn] = string.Empty;
                }
            }
            else
            {
                // Если пользователь отменил ввод, автоматически генерируем уникальное имя
                string autoColumnName = GenerateUniqueColumnName("NewColumn");
                DataColumn newColumn = new DataColumn(autoColumnName, typeof(string));
                _dataTable.Columns.Add(newColumn);
                newColumn.SetOrdinal(Math.Min(index, _dataTable.Columns.Count - 1));

                foreach (DataRow row in _dataTable.Rows)
                {
                    row[newColumn] = string.Empty;
                }
            }
        }

        // Генерация уникального имени столбца
        private string GenerateUniqueColumnName(string baseName)
        {
            int suffix = 1;
            string newName = baseName;
            while (_dataTable.Columns.Contains(newName))
            {
                newName = $"{baseName}_{suffix}";
                suffix++;
            }
            return newName;
        }

        // Получение индекса выбранной строки
        private int GetSelectedRowIndex()
        {
            if (EditDataGrid.SelectedItem is DataRowView selectedRow)
            {
                return _dataTable.Rows.IndexOf(selectedRow.Row);
            }
            return -1;
        }

        // Получение индекса выбранного столбца
        private int GetSelectedColumnIndex()
        {
            if (EditDataGrid.SelectedCells.Count > 0)
            {
                var selectedCell = EditDataGrid.SelectedCells[0];
                var column = selectedCell.Column;
                if (column != null)
                {
                    return column.DisplayIndex;
                }
            }
            return -1;
        }

        #endregion

        // Метод для обновления привязки данных к DataGrid
        private void RefreshDataGrid()
        {
            // Получаем текущий view
            var view = CollectionViewSource.GetDefaultView(EditDataGrid.ItemsSource);

            if (view != null)
            {
                view.Refresh();
            }
        }

        // Обработчик изменения выбранных ячеек (опционально)
        private void EditDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
        {
            // Дополнительная логика при изменении выбора (если требуется)
        }

        // Обработчик кнопки Экспорта файла
        private void ExportButton_Click(object sender, RoutedEventArgs e)
        {
            // Выбор разделителя (табуляция)
            string delimiter = "\t";

            SaveFileDialog sfd = new SaveFileDialog
            {
                Filter = "Text files (*.txt)|*.txt",
                FileName = "EditedCombinedMagneteFile.txt"
            };

            if (sfd.ShowDialog() == true)
            {
                try
                {
                    using (StreamWriter sw = new StreamWriter(sfd.FileName, false, Encoding.UTF8))
                    {
                        // Запись заголовков столбцов
                        string[] headers = _dataTable.Columns
                            .Cast<DataColumn>()
                            .Select(column => column.ColumnName)
                            .ToArray();
                        sw.WriteLine(string.Join(delimiter, headers));

                        // Запись данных строк
                        foreach (DataRow row in _dataTable.Rows)
                        {
                            string[] fields = new string[_dataTable.Columns.Count];
                            for (int i = 0; i < _dataTable.Columns.Count; i++)
                            {
                                string field = row[i].ToString();
                                // Если поле содержит разделитель, обрамляем его в кавычки
                                if (field.Contains(delimiter))
                                {
                                    field = $"\"{field}\"";
                                }
                                fields[i] = field;
                            }
                            sw.WriteLine(string.Join(delimiter, fields));
                        }
                    }

                    MessageBox.Show($"Файл успешно экспортирован по адресу:\n{sfd.FileName}", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Ошибка при сохранении файла:\n{ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
    }
}

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace TxtProcessorApp
{
    public partial class MainWindow : Window
    {
        // Словарь для хранения данных из .txt файлов. Ключ - имя файла, значение - список строк данных.
        private Dictionary<string, List<string[]>> txtFileData = new Dictionary<string, List<string[]>>();

        // Словарь для хранения данных из .magnete файлов. Ключ - имя файла, значение - список строк данных.
        private Dictionary<string, List<string[]>> magneteFileData = new Dictionary<string, List<string[]>>();

        // Хранение объединённых данных для дальнейшего редактирования
        private DataTable combinedDataTable = null;

        public MainWindow()
        {
            InitializeComponent();
        }

        #region Обработчики загрузки файлов .txt

        // Обработчик кнопки загрузки .txt файлов
        private void LoadTxtFiles_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                Multiselect = true,
                Filter = "Text files (*.txt)|*.txt"
            };

            if (ofd.ShowDialog() == true)
            {
                foreach (var file in ofd.FileNames)
                {
                    ProcessTxtFile(file);
                }

                // Обновляем TabControl с вкладками для каждого .txt файла
                PopulateTxtTabControl();

                // Деактивируем кнопку редактирования до объединения
                EditExportButton.IsEnabled = false;
                combinedDataTable = null;
            }
        }

        // Метод для обработки отдельного .txt файла
        private void ProcessTxtFile(string filePath)
        {
            List<string[]> processedLines = new List<string[]>();

            try
            {
                var lines = File.ReadAllLines(filePath).Skip(11); // Пропуск первых 11 строк

                foreach (var line in lines)
                {
                    if (string.IsNullOrWhiteSpace(line))
                        continue;

                    var columns = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    if (columns.Length == 0)
                        continue;

                    // Проверка первого столбца
                    if (columns[0].ToLower() == "nan" || string.IsNullOrWhiteSpace(columns[0]))
                        continue;

                    // Создаем список для новых столбцов
                    List<string> newColumns = new List<string>();

                    // Добавляем столбцы, кроме первого
                    for (int i = 1; i < columns.Length; i++)
                    {
                        newColumns.Add(columns[i]);
                    }

                    processedLines.Add(newColumns.ToArray());
                }

                // Добавляем обработанные данные в словарь
                string fileName = System.IO.Path.GetFileName(filePath);

                // Проверяем, если файл уже загружен, добавляем суффикс
                string originalFileName = fileName;
                int duplicateCount = 1;
                while (txtFileData.ContainsKey(fileName))
                {
                    fileName = $"{System.IO.Path.GetFileNameWithoutExtension(originalFileName)}_{duplicateCount}{System.IO.Path.GetExtension(originalFileName)}";
                    duplicateCount++;
                }

                txtFileData[fileName] = processedLines;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Ошибка при обработке файла {filePath}:\n{ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // Метод для заполнения TabControl вкладками для каждого .txt файла
        private void PopulateTxtTabControl()
        {
            FilesTabControl.Items.Clear();

            foreach (var kvp in txtFileData)
            {
                string fileName = kvp.Key;
                List<string[]> data = kvp.Value;

                // Создаем DataGrid для текущего файла
                DataGrid dataGrid = new DataGrid
                {
                    AutoGenerateColumns = true,
                    IsReadOnly = true
                };

                // Преобразуем данные в DataTable
                DataTable dataTable = ConvertToDataTable(data);
                dataGrid.ItemsSource = dataTable.DefaultView;

                // Создаем вкладку
                TabItem tabItem = new TabItem
                {
                    Header = fileName,
                    Content = dataGrid
                };

                FilesTabControl.Items.Add(tabItem);
            }
        }

        #endregion

        #region Обработчики загрузки файлов .magnete

        // Обработчик кнопки загрузки .magnete файлов
        private void LoadMagneteFiles_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                Multiselect = true,
                Filter = "Magnete files (*.magnete)|*.magnete"
            };

            if (ofd.ShowDialog() == true)
            {
                foreach (var file in ofd.FileNames)
                {
                    ProcessMagneteFile(file);
                }

                MessageBox.Show("Файлы .magnete успешно загружены.", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }

        // Метод для обработки отдельного .magnete файла
        private void ProcessMagneteFile(string filePath)
        {
            List<string[]> processedLines = new List<string[]>();

            try
            {
                var lines = File.ReadAllLines(filePath).Skip(11); // Пропуск первых 11 строк (если применимо)

                foreach (var line in lines)
                {
                    if (string.IsNullOrWhiteSpace(line))
                        continue;

                    var columns = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    if (columns.Length == 0)
                        continue;

                    // Проверка первого столбца
                    if (columns[0].ToLower() == "nan" || string.IsNullOrWhiteSpace(columns[0]))
                        continue;

                    // Создаем список для новых столбцов
                    List<string> newColumns = new List<string>();

                    // Добавляем столбцы, кроме первого
                    for (int i = 0; i < columns.Length; i++)
                    {
                        newColumns.Add(columns[i]);
                    }

                    processedLines.Add(newColumns.ToArray());
                }

                // Добавляем обработанные данные в словарь
                string fileName = System.IO.Path.GetFileName(filePath);

                // Проверяем, если файл уже загружен, добавляем суффикс
                string originalFileName = fileName;
                int duplicateCount = 1;
                while (magneteFileData.ContainsKey(fileName))
                {
                    fileName = $"{System.IO.Path.GetFileNameWithoutExtension(originalFileName)}_{duplicateCount}{System.IO.Path.GetExtension(originalFileName)}";
                    duplicateCount++;
                }

                magneteFileData[fileName] = processedLines;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Ошибка при обработке файла {filePath}:\n{ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        #endregion

        #region Общие методы

        // Метод для преобразования списка строк в DataTable с нужными названиями столбцов
        private DataTable ConvertToDataTable(List<string[]> data)
        {
            DataTable dt = new DataTable();

            if (data == null || data.Count == 0)
                return dt;

            // Создание столбцов с заданными названиями
            dt.Columns.Add("№");
            dt.Columns.Add("BASE-1");
            dt.Columns.Add("Noise");
            dt.Columns.Add("Time");
            dt.Columns.Add("Time UTC");

            // Добавление строк
            foreach (var row in data)
            {
                DataRow dr = dt.NewRow();
                dr["№"] = row.Length > 0 ? row[0] : string.Empty;
                dr["BASE-1"] = row.Length > 1 ? row[1] : string.Empty;
                dr["Noise"] = row.Length > 2 ? row[2] : string.Empty;
                dr["Time"] = row.Length > 3 ? row[3] : string.Empty;
                dr["Time UTC"] = row.Length > 4 ? row[4] : string.Empty;
                dt.Rows.Add(dr);
            }

            return dt;
        }

        // Обработчик кнопки Объединить файлы (предполагается только для .txt файлов)
        private void CombineFiles_Click(object sender, RoutedEventArgs e)
        {
            if (!txtFileData.Any())
            {
                MessageBox.Show("Нет загруженных .txt файлов для объединения.", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            List<string[]> combinedData = new List<string[]>();
            int lineNumber = 1;

            foreach (var file in txtFileData.Values)
            {
                foreach (var row in file)
                {
                    if (row.Length < 3)
                        continue; // Убедитесь, что есть минимум 3 столбца

                    // Извлечение необходимых столбцов
                    string secondColumn = row[1];
                    string thirdColumn = row.Length > 1 ? row[2] : string.Empty;
                    string fourthColumn = row.Length > 2 ? row[3] : "0"; // Если нет 4-го столбца, используем "0"

                    // Обработка пятого столбца
                    if (double.TryParse(fourthColumn, NumberStyles.Any, CultureInfo.InvariantCulture, out double number))
                    {
                        double divided = number / 24;
                        TimeSpan time = TimeSpan.FromDays(divided);
                        string timeString = time.ToString(@"hh\:mm\:ss");
                        combinedData.Add(new string[]
                        {
                            lineNumber.ToString(),
                            secondColumn,
                            thirdColumn,
                            fourthColumn,
                            timeString
                        });
                    }
                    else
                    {
                        combinedData.Add(new string[]
                        {
                            lineNumber.ToString(),
                            secondColumn,
                            thirdColumn,
                            fourthColumn,
                            "InvalidNumber"
                        });
                    }

                    lineNumber++;
                }
            }

            // Преобразуем объединённые данные в DataTable с нужными названиями столбцов
            combinedDataTable = ConvertToCombinedDataTable(combinedData);

            // Активируем кнопку редактирования
            EditExportButton.IsEnabled = true;

            MessageBox.Show("Файлы успешно объединены. Теперь вы можете отредактировать данные и экспортировать.", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        // Метод для преобразования объединённых данных в DataTable с нужными названиями столбцов
        private DataTable ConvertToCombinedDataTable(List<string[]> data)
        {
            DataTable dt = new DataTable();

            if (data == null || data.Count == 0)
                return dt;

            // Создание столбцов согласно требованиям
            dt.Columns.Add("№");
            dt.Columns.Add("BASE-1");
            dt.Columns.Add("Noise");
            dt.Columns.Add("Time");
            dt.Columns.Add("Time UTC");

            // Добавление строк
            foreach (var row in data)
            {
                DataRow dr = dt.NewRow();
                dr["№"] = row.Length > 0 ? row[0] : string.Empty;
                dr["BASE-1"] = row.Length > 1 ? row[1] : string.Empty;
                dr["Noise"] = row.Length > 2 ? row[2] : string.Empty;
                dr["Time"] = row.Length > 3 ? row[3] : string.Empty;
                dr["Time UTC"] = row.Length > 4 ? row[4] : string.Empty;
                dt.Rows.Add(dr);
            }

            return dt;
        }

        // Обработчик кнопки Редактировать и Экспортировать
        private void EditAndExport_Click(object sender, RoutedEventArgs e)
        {
            if (combinedDataTable == null)
            {
                MessageBox.Show("Нет объединённых данных для редактирования.", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            // Создаём и открываем окно редактирования
            EditWindow editWindow = new EditWindow(combinedDataTable);
            editWindow.Owner = this;
            editWindow.ShowDialog();

            // После закрытия EditWindow обновляем данные в TabControl (опционально)
            // Можно перезагрузить TabControl, чтобы отобразить отредактированные данные
            // В данном примере это не делается, но можно реализовать по желанию
        }

        #endregion

        #region Обработчик открытия окна просмотра .magnete файлов

        private void OpenMagneteView_Click(object sender, RoutedEventArgs e)
        {
            if (!magneteFileData.Any())
            {
                MessageBox.Show("Нет загруженных .magnete файлов для просмотра.", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            // Создаём и открываем окно просмотра .magnete файлов
            MagneteWindow magneteWindow = new MagneteWindow(magneteFileData);
            magneteWindow.Owner = this;
            magneteWindow.Show();
        }

        #endregion
    }
}

<Window x:Class="TxtProcessorApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TxtProcessorApp"
        Title="Txt Processor" Height="600" Width="900">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- Панель кнопок загрузки файлов -->
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <Button Content="Загрузить .txt файлы" Width="150" Height="30" Click="LoadTxtFiles_Click"/>
            <Button Content="Загрузить .magnete файлы" Width="180" Height="30" Click="LoadMagneteFiles_Click" Margin="10,0,0,0"/>
            <Button Content="Просмотр .magnete файлов" Width="180" Height="30" Click="OpenMagneteView_Click" Margin="10,0,0,0"/>
        </StackPanel>

        <!-- TabControl для отображения .txt файлов -->
        <TabControl x:Name="FilesTabControl" Grid.Row="1" Margin="0,10,0,10"/>

        <!-- Кнопка объединения файлов и редактирования -->
        <StackPanel Grid.Row="2" Orientation="Horizontal">
            <Button Content="Объединить файлы" Width="150" Height="30" Click="CombineFiles_Click"/>
            <Button Content="Редактировать и Экспортировать" Width="200" Height="30" Margin="10,0,0,0" Click="EditAndExport_Click" IsEnabled="False" x:Name="EditExportButton"/>
        </StackPanel>
    </Grid>
</Window>

<Window x:Class="TxtProcessorApp.EditWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TxtProcessorApp"
        Title="Редактирование данных" Height="600" Width="900">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- DataGrid для отображения и редактирования данных -->
        <DataGrid x:Name="EditDataGrid" Grid.Row="0" AutoGenerateColumns="True" 
                  CanUserAddRows="True" CanUserDeleteRows="True" 
                  IsReadOnly="False" 
                  SelectionUnit="CellOrRowHeader" 
                  SelectedCellsChanged="EditDataGrid_SelectedCellsChanged">
            <!-- Контекстное меню для вставки строк и столбцов -->
            <DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Вставить строку выше" Click="InsertRowAbove_Click"/>
                    <MenuItem Header="Вставить строку ниже" Click="InsertRowBelow_Click"/>
                    <Separator/>
                    <MenuItem Header="Вставить столбец слева" Click="InsertColumnLeft_Click"/>
                    <MenuItem Header="Вставить столбец справа" Click="InsertColumnRight_Click"/>
                </ContextMenu>
            </DataGrid.ContextMenu>
        </DataGrid>

        <!-- Панель кнопок ниже DataGrid -->
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,10,0,0">
            <!-- Элемент управления для выбора разделителя -->
            <ComboBox x:Name="DelimiterComboBox" Width="100" Height="30" SelectedIndex="0">
                <ComboBoxItem Content="Пробел"/>
                <ComboBoxItem Content="Табуляция"/>
                <ComboBoxItem Content="Запятая"/>
            </ComboBox>
            <Button Content="Экспортировать файл" Width="150" Height="30" Margin="10,0,0,0" Click="ExportButton_Click"/>
        </StackPanel>
    </Grid>
</Window>

<Window x:Class="TxtProcessorApp.InputDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Ввод" Height="150" Width="400" WindowStartupLocation="CenterOwner" ResizeMode="NoResize">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock x:Name="PromptTextBlock" Grid.Row="0" Text="Prompt:" Margin="0,0,0,10" TextWrapping="Wrap"/>

        <TextBox x:Name="ResponseTextBox" Grid.Row="1" Height="25"/>

        <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
            <Button Content="OK" Width="75" Margin="0,0,10,0" IsDefault="True" Click="OK_Click"/>
            <Button Content="Отмена" Width="75" IsCancel="True"/>
        </StackPanel>
    </Grid>
</Window>