商品库存管理系统(MYSQL)

商品库存管理系统 运行效果

商品库存管理系统 功能模块

新增商品功能模块

库存功能

删除、添加商品种类、查询、修改数量、导出成为excel

主窗口UI设计

  1. 设置主窗口的背景颜色
  2. 以及各个控件的添加和控件的风格

遇到的问题:

设置窗口背景的方法

复制代码
   QPalette palette=this->palette();
    palette.setColor(QPalette::Background,"#BDE582");//窗口颜色
    this->setPalette(palette);

表格控件初始化

  1. 表头、列数、行数

  2. 设置列宽

    void MainWidget::tableWidgetInt()
    {
    QStringList head;
    ui->tableWidget->setRowCount(10);
    ui->tableWidget->setColumnCount(8);
    head<<"编号"<<"名称"<<"数量"<<"单价"<<"供应商家"<<"负责人"<<"入库时间"<<"出库时间";
    ui->tableWidget->setHorizontalHeaderLabels(head);//设置表头
    ui->tableWidget->setColumnWidth(0,40);//设置列宽
    ui->tableWidget->setColumnWidth(2,60);
    ui->tableWidget->setColumnWidth(3,60);
    ui->tableWidget->setColumnWidth(4,140);
    ui->tableWidget->setColumnWidth(5,100);
    ui->tableWidget->setColumnWidth(6,160);
    ui->tableWidget->setColumnWidth(7,160);

    }

连接数据库

  1. 使用QODBC的方式
  2. 连接数据库的IP、端口、数据库名、密码
复制代码
   void MainWidget::sqlConnect()
   {
       QSqlDatabase db=QSqlDatabase::addDatabase("QODBC");
       db.setHostName("127.0.0.1");
       db.setPort(3306);
       db.setDatabaseName("stockmsdb");
       db.setPassword("5320240388");
       bool bok=db.open();
       if(!bok)
       {
           QMessageBox::information(this,"提示","连接不成功");
       }
   }

初始化mysql数据到Qt表格中

  1. 查询数据的方法:根据mysql的指定字段和对应字段的数据,使用where 查询。用字符串的方式组合生成sql语句。然后传给mysql

  2. mysql的结果回传给qt的方法:sqlquery循环读取每个字段对应的数据,得到的数据转换成字符串,然后传给tablewidget的item中

  3. 查询只会需要更新表,重新生成

    void MainWidget::tableDataInt()
    {
    QString str=("select *from goods;");//sql查询语句格式
    QSqlQuery sql;
    if(!sql.exec(str))//进行查询
    {
    QMessageBox::information(this,"提示","查询不成功");
    return ;
    }
    int j=0;
    while(sql.next())//获取查询到的结果
    {
    for(int i=0;i<=7;i++)
    {
    ui->tableWidget->setItem(j,i,new QTableWidgetItem(sql.value(i).toString()));
    }
    j++;
    }

    }

新增商品新种类导数据到mysql中

  1. 设置新增商品的对话框的UI
  2. 将对话框得到的数据导入字符串中
  3. 将字符串转sql语句转给mysql数据库
  4. 其中需要解决点:获取当前入库时间,以及对话框为空的问题

UI设计:

插入数据设计:

复制代码
void add_product::on_pushButton_add_clicked()
{
    //获取插入数据
    QString id=ui->lineEdit_id->text();
    if(id.isEmpty())
    {
        QMessageBox::critical(this,"警告","编号不能为空!");
           ui->lineEdit_id->setFocus();
           return;
    }
    QString name="'"+ui->lineEdit_name->text()+"'";
    QString amount="'"+ui->lineEdit_amount->text()+"'";
    QString price="'"+ui->lineEdit_price->text()+"'";
    QString saller="'"+ui->lineEdit_saller->text()+"'";
    QString director="'"+ui->lineEdit_director->text()+"'";

    QString intodatetime="'"+QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")+"'";//获取mysql对应格式时间

    QString targetdata=id+","+name+","+amount+","+price+","+saller+","+director+","+intodatetime+","+"NULL";
   //组合生成sql代码
    QString insertsent=QString("insert into goods (id,product_name,product_amount,product_price,product_saller,product_director,product_into_time,product_out_time)values(%1)").arg(targetdata);
      //进行执行sql
     QSqlQuery sql;
     if(!sql.exec(insertsent))
     {
         QMessageBox::critical(this,"警告","新增商品失败");
     }
     else
     {
         QMessageBox::information(this,"通知","新增商品成功");
     }

}

商品查询

复制代码
 QString name=ui->lineEdit_name->text();//根据商品名查询
    if(name.isEmpty())
    {
         QMessageBox::critical(this,"警告","商品名称不能为空");
         ui->lineEdit_name->setFocus();
         return;
    }
    ui->tableWidget->clear();//清除之前的表只为得到对应数据
    QString selectsql=QString("select *from goods where product_name=%1;").arg("'"+name+"'");
    QSqlQuery sql;
    if(!sql.exec(selectsql))
    {
        QMessageBox::information(this,"提示","查询不成功");
        return ;
    }
    int j=0;
    while(sql.next())
    {
        for(int i=0;i<=7;i++)
        {
            ui->tableWidget->setItem(j,i,new QTableWidgetItem(sql.value(i).toString()));
        }
        j++;
    }

商品入库

  1. 修改商品的数量
  2. 用字符串的方式获取商品数量
  3. 将字符串作为sql语句传给mysql

UI设计:获取当前所有id值

复制代码
void add_amount::interfaceInit()
{
    QSqlQuery sql;
    QString getid=QString("select id from goods");
    if(!sql.exec(getid))
    {
        QMessageBox::information(this,"提示","获取不成功");
        return ;
    }
    while(sql.next())
    {
        ui->comboBox_id->addItem(sql.value(0).toString());
    }
}

更改数量

获取当前已有的数量

复制代码
QString selectId=ui->comboBox_id->currentText();
    QString selectAmount=QString("select product_amount from goods where id=%1;").arg("'"+selectId+"'");//获取当前id对应的数量
    QSqlQuery sql;
    if(!sql.exec(selectAmount))
    {
         QMessageBox::critical(this,"警告","查询失败1");
         return ;
    }
    int currentquantity;
    while(sql.next())
    {
     currentquantity=sql.value(0).toInt();
    }

将已有数量与新加的数量相加,然后发送信号让主页面自动更改窗口

复制代码
  QString updateAmount=QString("update goods set product_amount=%1 where id=%2;").arg(QString::number(sumQuantity)).arg(selectId);
    if(!sql.exec(updateAmount))
    {
         QMessageBox::critical(this,"警告","查询失败2");
         return ;
    }
    else
    {emit dataConfirmed(); // ✅ 发射信号给主窗口,让主窗口自动更新页面
        QMessageBox::information(this,"通知","插入成功");

    }

商品出库

  1. 获取数据库中对应商品数据

  2. 通过下拉框的改变,进行更改商品数据,首先获取id值,找到对应id值的数据,添加数量。

  3. 将数据修改之后转换为sql语句发给mysql中

    复制代码
    void delete_amount::on_pushButton_out_clicked()//减少数量
    {
        QString selectId=ui->comboBox_id->currentText();
        QString selectAmount=QString("select product_amount from goods where id=%1;").arg("'"+selectId+"'");
        QSqlQuery sql;
        if(!sql.exec(selectAmount))
        {
             QMessageBox::critical(this,"警告","查询失败1");
             return ;
        }
        int currentquantity;
        while(sql.next())
        {
         currentquantity=sql.value(0).toInt();
        }
        int sumQuantity=(currentquantity-ui->lineEdit_amount->text().toInt())>=0?currentquantity-ui->lineEdit_amount->text().toInt():0;//防止数量为负数
    
        QString updateAmount=QString("update goods set product_amount=%1 where id=%2;").arg(QString::number(sumQuantity)).arg(selectId);
        if(!sql.exec(updateAmount))
        {
             QMessageBox::critical(this,"警告","出库失败2");
             return ;
        }
        else
        {
            emit dataConfirmed();
            QMessageBox::information(this,"通知","出库成功");
        }
    }
    
    void delete_amount::interfaceInit()//ui设计
    {
        QSqlQuery sql;
        QString getid=QString("select id from goods");
        if(!sql.exec(getid))
        {
            QMessageBox::information(this,"提示","获取不成功");
            return ;
        }
        while(sql.next())
        {
            ui->comboBox_id->addItem(sql.value(0).toString());
        }
    }

下架商品

  1. 找到当前选中行

  2. 获取选中行的id

  3. 根据id对mysql的一行数据进行删除

  4. 刷新当前表格

    //清空商品
    //获取当前的item
    if(ui->tableWidget->currentRow()>=0)//判断当前是否选中行
    {
    int btn= QMessageBox::information(this,"删除数据","你确定删除当前选中数据?",QMessageBox::Ok,QMessageBox::No);
    if(btn==QMessageBox::Ok)
    {
    //获取当前item的所在行
    int iRow=ui->tableWidget->currentRow();
    QString delid=ui->tableWidget->model()->index(iRow,0).data().toString();//获取这一行的id
    QString selectAmount=QString("select *from goods where id=%1;").arg("'"+delid+"'");
    QSqlQuery sql;
    if(!sql.exec(selectAmount))
    {
    QMessageBox::critical(this,"警告","查询id失败");
    return ;
    }
    QString delstr=QString("delete from goods where id='%1';").arg(delid);
    if(!sql.exec(delstr))
    {
    QMessageBox::critical(this,"警告","删除失败");
    return ;
    }
    else
    {
    ui->tableWidget->clear();
    tableWidgetInt();
    QMessageBox::information(this,"通知","删除商品成功");

    复制代码
     }
     }}
     else
     {
         QMessageBox::information(this,"删除数据","你没有选中要删除的行",QMessageBox::Ok,QMessageBox::No);
         return ;
     }

表格数据转Excel

  1. 生成文件名:使用当前时间作为文件名前缀

  2. 选择保存路径

  3. 创建Excel对象:通过COM接口操作Excel

  4. 写入表头和数据

    复制代码
    //将时间作为文件名前缀
     QString timestr = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm");
     //创建文件并获取文件名
     QString strFileName = QFileDialog::getSaveFileName(this, "保存文件",
         QString("./%1%2.xlsx").arg(timestr).arg("_kcgl"), "Excel Files(*.xlsx)"); // ✅ 修复5: 改为.xlsx
    
     if(!strFileName.isEmpty())
     {
         // 测试文件创建权限后,立即删除测试文件,避免占用
         QFile testFile(strFileName);
         if(testFile.open(QIODevice::WriteOnly))
         {
             testFile.close();
             testFile.remove(); // ✅ 修复6: 立即删除,释放文件占用
             qDebug() << "文件路径权限检查通过。";
    
             QAxObject *excel = new QAxObject();
             if(excel->setControl("Excel.Application"))
             {
                 excel->dynamicCall("SetVisible(bool)", false);
                 excel->setProperty("DisplayAlerts", false);
    
                 // 获取工作簿集合
                 QAxObject *workbooks = excel->querySubObject("WorkBooks");
                 if(!workbooks) { /* 错误处理 */ }
                 workbooks->dynamicCall("Add");
    
                 // 获取活动工作簿
                 QAxObject *workbook = excel->querySubObject("ActiveWorkBook");
                 if(!workbook) { /* 错误处理 */ }
    
                 // 获取第一个工作表
                 QAxObject *worksheets = workbook->querySubObject("Worksheets");
                 QAxObject *worksheet = worksheets->querySubObject("Item(int)", 1); // 也可用 Worksheets(int)
                 if(!worksheet) { /* 错误处理 */ }
    
                 // ✅ 修复2: 添加表头安全检查
                 int columnCount = ui->tableWidget->columnCount();
                 for(int i = 0; i < columnCount; i++)
                 {
                     QAxObject *cell = worksheet->querySubObject("Cells(int,int)", 1, i+1);
                     if(cell) {
                         QTableWidgetItem *header = ui->tableWidget->horizontalHeaderItem(i);
                         if(header) {
                             cell->dynamicCall("SetValue(const QString&)", header->text());
                         }
                         delete cell; // ✅ 修复1: 循环内立即释放
                     }
                 }
    
                 // ✅ 修复2 & 4: 添加数据安全检查,并移除多余的"\t"
                 int rowCount = ui->tableWidget->rowCount();
                 for(int i = 0; i < rowCount; i++)
                 {
                     for(int j = 0; j < columnCount; j++)
                     {
                         QAxObject *cell = worksheet->querySubObject("Cells(int,int)", i+2, j+1);
                         if(cell) {
                             QTableWidgetItem *item = ui->tableWidget->item(i, j);
                             QString text = item ? item->text() : ""; // ✅ 修复4: 不再添加 "\t"
                             // 可选:处理以0开头的数字等格式
                             if(text.toInt() == text.toDouble() && text.length()>1 && text.startsWith('0')) {
                                 text = "'" + text;
                             }
                             cell->dynamicCall("SetValue(const QString&)", text);
                             delete cell; // ✅ 修复1: 循环内立即释放
                         }
                     }
                 }
    
                 // 保存文件
                 workbook->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(strFileName));
                 workbook->dynamicCall("Close()");
                 excel->dynamicCall("Quit()");
    
                 // ✅ 修复3: 按创建顺序的反序,安全释放所有COM对象
                 delete worksheet;
                 delete worksheets;
                 delete workbook;
                 delete workbooks;
                 delete excel;
    
                 QMessageBox::information(this, "成功", "导出完成!");
    
             } else {
                 QMessageBox::critical(this, "错误", "无法启动Excel。");
                 delete excel;
             }
         } else {
             QMessageBox::critical(this, "错误",
                 QString("无法创建文件:\n%1\n错误:%2").arg(strFileName).arg(testFile.errorString()));
         }
     }

商品汇总

  1. 读取数据库的内容

  2. 然后将单价与数量用sql语句进行合成,生成总价

  3. 用按键进行汇总

  4. 以及进行保存

    void datasum::tableWidgetInt()
    {
    QStringList ls;
    ls<<"编号"<<"名称"<<"数量"<<"单价"<<"总价"<<"供应商家"<<"负责人"<<"入库时间"<<"出库时间";
    ui->tableWidget->setRowCount(100);
    ui->tableWidget->setColumnCount(9);
    ui->tableWidget->setHorizontalHeaderLabels(ls);
    ui->tableWidget->setColumnWidth(0,40);
    ui->tableWidget->setColumnWidth(2,60);
    ui->tableWidget->setColumnWidth(3,60);
    ui->tableWidget->setColumnWidth(4,40);
    ui->tableWidget->setColumnWidth(5,140);
    ui->tableWidget->setColumnWidth(6,120);
    ui->tableWidget->setColumnWidth(7,160);
    ui->tableWidget->setColumnWidth(8,160);

    }

    void datasum::tableDataInt()
    {
    QSqlQuery sql;
    QString selectsql="select *from goods;";
    if(sql.exec(selectsql))
    {
    int i=0;
    while(sql.next())
    {
    for(int j=0;j<ui->tableWidget->columnCount();j++)
    {
    if(j>=4)
    {
    ui->tableWidget->setItem(i,j+1,new QTableWidgetItem(sql.value(j).toString()));
    }
    else{
    ui->tableWidget->setItem(i,j,new QTableWidgetItem(sql.value(j).toString()));
    }

    复制代码
         }
                     double amount=ui->tableWidget->item(i,2)->text().toInt();
                     double price=ui->tableWidget->item(i,3)->text().toInt();
                     ui->tableWidget->setItem(i,4,new QTableWidgetItem(QString::number(amount*price)));
         i++;
         }
     }

    }

    void datasum::on_pushButton_data_sum_clicked()
    {
    tableWidgetInt();
    tableDataInt();

    }

相关推荐
什么都不会的Tristan21 小时前
Feed流(关注推送)
java·前端·数据库
wu_jing_sheng021 小时前
黑龙江省保险补贴Shapefile转换工具:GIS数据处理自动化实践
大数据·数据库·人工智能
GrowingYi21 小时前
分布式数据库事务实现
数据库·分布式·database
托尼吴1 天前
milvus 向量数据库学习笔记-基础认识
数据库·学习·milvus
徐同保1 天前
使用n8n中的HTTP Request节点清空pinecones向量数据库
数据库·网络协议·http
小北方城市网1 天前
第 9 课:Python 全栈项目性能优化实战|从「能用」到「好用」(企业级优化方案|零基础落地)
开发语言·数据库·人工智能·python·性能优化·数据库架构
ChineHe1 天前
Redis入门篇001_Redis简介与特性
数据库·redis·缓存
仓颉也为难1 天前
全表扫和索引在哪种场景哪个效率高、基线分水岭在哪
数据库
Anthony_2311 天前
MySql常用SQL命令
服务器·数据库·sql·mysql·http·oracle·udp