wpf对excel中的两列数据进行拟合,输出函数表达式和函数图像,并列出需要导入的nuget包和前端HTML代码
时间: 2024-06-08 20:11:24 浏览: 190
要在WPF应用程序中对Excel中的两列数据进行拟合,您可以使用Math.NET Numerics NuGet包来执行拟合。以下是所需的nuget包:
- MathNet.Numerics
以下是一个示例WPF应用程序,该应用程序允许用户选择一个Excel文件,然后选择要用于拟合的两列数据。应用程序将显示拟合函数的表达式和图形。
XAML代码:
```xml
<Window x:Class="ExcelDataFitting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Excel Data Fitting" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Excel File:"/>
<TextBox Grid.Row="0" Grid.Column="1" Width="200" Text="{Binding ExcelFilePath}" IsReadOnly="True"/>
<Button Grid.Row="0" Grid.Column="2" Content="Browse" Margin="5" Command="{Binding BrowseCommand}"/>
<Label Grid.Row="1" Grid.Column="0" Content="X Data Column:"/>
<ComboBox Grid.Row="1" Grid.Column="1" Width="200" ItemsSource="{Binding ExcelColumns}" SelectedItem="{Binding XDataColumn}"/>
<Label Grid.Row="2" Grid.Column="0" Content="Y Data Column:"/>
<ComboBox Grid.Row="2" Grid.Column="1" Width="200" ItemsSource="{Binding ExcelColumns}" SelectedItem="{Binding YDataColumn}"/>
<Grid Grid.Row="3" Grid.ColumnSpan="3">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding FunctionExpression}" Margin="5"/>
<Image Grid.Row="1" Source="{Binding FunctionGraph}" Stretch="Uniform" Margin="5"/>
</Grid>
</Grid>
</Window>
```
ViewModel代码:
```csharp
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using MathNet.Numerics;
using MathNet.Numerics.Fitting;
using MathNet.Numerics.LinearAlgebra;
namespace ExcelDataFitting
{
public class MainWindowViewModel : INotifyPropertyChanged
{
private string _excelFilePath;
private List<string> _excelColumns;
private string _xDataColumn;
private string _yDataColumn;
private string _functionExpression;
private BitmapImage _functionGraph;
public string ExcelFilePath
{
get { return _excelFilePath; }
set
{
_excelFilePath = value;
OnPropertyChanged(nameof(ExcelFilePath));
}
}
public List<string> ExcelColumns
{
get { return _excelColumns; }
set
{
_excelColumns = value;
OnPropertyChanged(nameof(ExcelColumns));
}
}
public string XDataColumn
{
get { return _xDataColumn; }
set
{
_xDataColumn = value;
OnPropertyChanged(nameof(XDataColumn));
UpdateFunction();
}
}
public string YDataColumn
{
get { return _yDataColumn; }
set
{
_yDataColumn = value;
OnPropertyChanged(nameof(YDataColumn));
UpdateFunction();
}
}
public string FunctionExpression
{
get { return _functionExpression; }
set
{
_functionExpression = value;
OnPropertyChanged(nameof(FunctionExpression));
}
}
public BitmapImage FunctionGraph
{
get { return _functionGraph; }
set
{
_functionGraph = value;
OnPropertyChanged(nameof(FunctionGraph));
}
}
public ICommand BrowseCommand { get; }
public MainWindowViewModel()
{
BrowseCommand = new RelayCommand(Browse);
}
private void Browse()
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".xlsx";
dlg.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm";
bool? result = dlg.ShowDialog();
if (result == true)
{
ExcelFilePath = dlg.FileName;
ExcelColumns = GetExcelColumns(dlg.FileName);
XDataColumn = ExcelColumns.FirstOrDefault();
YDataColumn = ExcelColumns.FirstOrDefault();
}
}
private List<string> GetExcelColumns(string fileName)
{
List<string> columns = new List<string>();
try
{
using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var dataSet = reader.AsDataSet();
foreach (DataTable table in dataSet.Tables)
{
foreach (DataColumn column in table.Columns)
{
columns.Add(column.ColumnName);
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error loading Excel file: " + ex.Message);
}
return columns;
}
private void UpdateFunction()
{
if (string.IsNullOrEmpty(ExcelFilePath) || string.IsNullOrEmpty(XDataColumn) || string.IsNullOrEmpty(YDataColumn))
{
FunctionExpression = null;
FunctionGraph = null;
return;
}
try
{
using (var stream = File.Open(ExcelFilePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var dataSet = reader.AsDataSet();
var dataTable = dataSet.Tables[0];
var xData = dataTable.AsEnumerable().Select(r => Convert.ToDouble(r[XDataColumn])).ToArray();
var yData = dataTable.AsEnumerable().Select(r => Convert.ToDouble(r[YDataColumn])).ToArray();
Tuple<double, double>[] points = new Tuple<double, double>[xData.Length];
for (int i = 0; i < xData.Length; i++)
{
points[i] = Tuple.Create(xData[i], yData[i]);
}
var coefficients = Fit.Polynomial(points, 2);
FunctionExpression = string.Format("{0:F4}x^2 + {1:F4}x + {2:F4}", coefficients[2], coefficients[1], coefficients[0]);
var xMin = xData.Min();
var xMax = xData.Max();
var xRange = xMax - xMin;
var xStep = xRange / 1000;
var xValues = Vector<double>.Build.Dense(1001, i => xMin + i * xStep);
var yValues = xValues.PointwiseMultiply(xValues).PointwiseMultiply(coefficients[2]).Add(xValues.PointwiseMultiply(coefficients[1])).Add(coefficients[0]);
var chart = new Chart(width: 800, height: 600)
.AddSeries(
name: "Function",
chartType: "line",
xValue: xValues.ToArray(),
yValues: yValues.ToArray())
.SetXAxis(title: XDataColumn)
.SetYAxis(title: YDataColumn);
using (var memoryStream = new MemoryStream())
{
chart.SaveImage(memoryStream, ChartImageFormat.Png);
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(memoryStream.ToArray());
bitmapImage.EndInit();
FunctionGraph = bitmapImage;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error fitting data: " + ex.Message);
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public RelayCommand(Action execute, Func<bool> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
```
此应用程序使用MathNet Numerics执行一个二次拟合,您可以使用其他函数库来执行不同类型的拟合。最后,您需要将NuGet包的引用添加到WPF项目中,并在App.xaml.cs中设置启动窗口:
```csharp
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow mainWindow = new MainWindow();
MainWindowViewModel viewModel = new MainWindowViewModel();
mainWindow.DataContext = viewModel;
mainWindow.Show();
}
}
```
这样,您就可以拟合Excel中的数据并显示图形和函数表达式了。
阅读全文