From a0987815ae7a95d2ad6a4bc71e99158edd4f6f08 Mon Sep 17 00:00:00 2001
From: whb <17803890193@163.com>
Date: Thu, 22 Aug 2024 10:15:06 +0800
Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E5=AF=BC=E5=85=A5=E8=A1=A8=E5=86=99?=
 =?UTF-8?q?=E5=85=A5tableName=E4=B8=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../stu/StuUserProfileDatabaseController.java |  31 +-
 .../marketing/util/excel/EasyExcelUtils.java  | 528 ++++++++++++++++++
 2 files changed, 557 insertions(+), 2 deletions(-)
 create mode 100644 src/main/java/com/sztzjy/marketing/util/excel/EasyExcelUtils.java

diff --git a/src/main/java/com/sztzjy/marketing/controller/stu/StuUserProfileDatabaseController.java b/src/main/java/com/sztzjy/marketing/controller/stu/StuUserProfileDatabaseController.java
index a90cf65..b1bd363 100644
--- a/src/main/java/com/sztzjy/marketing/controller/stu/StuUserProfileDatabaseController.java
+++ b/src/main/java/com/sztzjy/marketing/controller/stu/StuUserProfileDatabaseController.java
@@ -1,11 +1,15 @@
 package com.sztzjy.marketing.controller.stu;
 
+import cn.hutool.core.util.IdUtil;
 import com.alibaba.excel.EasyExcel;
 import com.sztzjy.marketing.annotation.AnonymousAccess;
 import com.sztzjy.marketing.config.ThreadPoolConfig;
+import com.sztzjy.marketing.entity.StuTableName;
+import com.sztzjy.marketing.entity.StuTableNameExample;
 import com.sztzjy.marketing.entity.StuUploadExcelUser;
 import com.sztzjy.marketing.entity.StuUser;
 import com.sztzjy.marketing.entity.dto.StuUserProfileDto;
+import com.sztzjy.marketing.mapper.StuTableNameMapper;
 import com.sztzjy.marketing.mapper.StuUploadExcelUserMapper;
 import com.sztzjy.marketing.service.StuUserProfileDatabaseService;
 import com.sztzjy.marketing.util.ResultEntity;
@@ -18,10 +22,15 @@ import io.swagger.annotations.ApiParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
 
 /**
  * @author 17803
@@ -42,7 +51,8 @@ public class StuUserProfileDatabaseController {
     @Autowired
     private StuUploadExcelUserMapper stuUploadExcelUserMapper;
 
-
+    @Autowired
+    private StuTableNameMapper stuTableNameMapper;
 
 
     @GetMapping("/getBaseInfo")
@@ -82,15 +92,32 @@ public class StuUserProfileDatabaseController {
     @ApiOperation("外部excel上传")
     @PostMapping("/uploadExcel")
     //@AnonymousAccess
+    @Transactional(rollbackFor = Exception.class)
     public ResultEntity uploadExcel(@RequestPart @ApiParam("文件") MultipartFile file,String userId) throws IOException {
-
         //读取文件内容  批量导入excel中    以文件名区分\
 
         String fileName = file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf("."));
 
+        //导入之前判断是否重复导入
+        StuTableNameExample stuTableNameExample = new StuTableNameExample();
+        stuTableNameExample.createCriteria().andUserIdEqualTo(userId).andTableNameEqualTo(fileName);
+        List<StuTableName> stuTableNames = stuTableNameMapper.selectByExample(stuTableNameExample);
+        if (!CollectionUtils.isEmpty(stuTableNames)){
+            return new ResultEntity<>(HttpStatus.OK,"文件已存在!");
+        }
+
+
         // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
         EasyExcel.read(file.getInputStream(), StuUploadExcelUser.class,new DemoDataListener(stuUploadExcelUserMapper,userId,fileName)).sheet().doRead();
 
+        StuTableName tableName = new StuTableName();
+        tableName.setUserId(userId);
+        tableName.setTableName(fileName);
+        tableName.setCreateTime(new Date());
+        tableName.setId((int) IdUtil.getSnowflakeNextId());
+        stuTableNameMapper.insertSelective(tableName);
+
+
         return new ResultEntity<>(HttpStatus.OK,"上传成功");
 
     }
diff --git a/src/main/java/com/sztzjy/marketing/util/excel/EasyExcelUtils.java b/src/main/java/com/sztzjy/marketing/util/excel/EasyExcelUtils.java
new file mode 100644
index 0000000..c9283be
--- /dev/null
+++ b/src/main/java/com/sztzjy/marketing/util/excel/EasyExcelUtils.java
@@ -0,0 +1,528 @@
+package com.sztzjy.marketing.util.excel;
+
+import cn.hutool.core.collection.CollUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.metadata.data.CellData;
+import com.alibaba.excel.metadata.data.WriteCellData;
+import com.alibaba.excel.write.handler.RowWriteHandler;
+import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.style.WriteCellStyle;
+import com.alibaba.excel.write.metadata.style.WriteFont;
+import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
+import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.*;
+
+
+public class EasyExcelUtils {
+
+    private static final Logger log = LoggerFactory.getLogger(EasyExcelUtils.class);
+
+    /**
+     * 导出Excel返回文件的File
+     *
+     * home.php?mod=space&uid=952169 data
+     * @param clazz
+     * @param fileName
+     */
+    public static <T> File exportReturnToFile(List<T> data, Class<T> clazz, String fileName) {
+        File file = null;
+        //名称拆分前后缀
+        //1.判断文件名是否有扩展
+        try {
+            if (StringUtils.isBlank(fileName)) {
+                file = File.createTempFile(fileName, "");
+            } else {
+                String[] parts = fileName.split("\\.");
+                String extension = "." + parts[parts.length - 1];
+                String name = fileName.substring(0, fileName.length() - extension.length() - 1);
+                file = File.createTempFile(name, extension);
+            }
+        } catch (IOException e) {
+            log.error("文件生成失败,文件名异常.异常信息:{}", e.getMessage());
+            throw new RuntimeException("文件生成失败,文件名异常");
+        }
+
+        //导出
+        EasyExcel.write(file, clazz)
+                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                .registerWriteHandler(defaultStylePolicyPolicy())
+                .sheet()
+                .doWrite(data);
+        return file;
+    }
+
+    /**
+     * EasyExce导出到浏览器(类模板方式)
+     *
+     * @param fileName 文件名
+     * @param response 响应对象
+     * @param data     数据集
+     * @param clazz    实体类模板
+     * @param <T>      泛型
+     */
+    public static <T> void export(String fileName, HttpServletResponse response, List<T> data, Class<T> clazz) throws IOException {
+        exportPublic(fileName, response, data, clazz, null);
+    }
+
+    /**
+     * EasyExce导出到浏览器(类模板方式)
+     *
+     * @param fileName                文件名
+     * @param response                响应对象
+     * @param data                    数据集
+     * @param clazz                   实体类模板
+     * @param excludeColumnFieldNames 忽略指定列导出根据字段名
+     * @param <T>                     泛型
+     */
+    public static <T> void export(String fileName, HttpServletResponse response, List<T> data, Class<T> clazz, List<String> excludeColumnFieldNames) throws IOException {
+        exportPublic(fileName, response, data, clazz, excludeColumnFieldNames);
+    }
+
+    /**
+     * export公共
+     *
+     * @param fileName                文件名
+     * @param response                响应对象
+     * @param data                    数据集
+     * @param clazz                   实体类模板
+     * @param excludeColumnFieldNames 忽略指定列导出根据字段名
+     * @param <T>                     泛型
+     * @throws IOException
+     */
+    private static <T> void exportPublic(String fileName, HttpServletResponse response, List<T> data, Class<T> clazz, List<String> excludeColumnFieldNames) throws IOException {
+
+        setResponse(response, fileName);
+
+        //导出
+        EasyExcel.write(response.getOutputStream(), clazz)
+                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                .registerWriteHandler(defaultStylePolicyPolicy())
+                .registerWriteHandler(new CustomCellWriteWidthConfig())
+//                .registerWriteHandler(new CustomCellWriteHeightConfig())
+                .sheet()
+                .excludeColumnFieldNames(excludeColumnFieldNames)
+                .doWrite(data);
+
+    }
+
+    /**
+     * EasyExce导出到浏览器(动态标题(字段)方式)
+     *
+     * @param fileName 文件名
+     * @param response 响应对象
+     * @param heads    标题(字段)
+     * @param data     数据
+     * @throws IOException
+     */
+    public static void export(String fileName, HttpServletResponse response, List<List<String>> heads, List<List<Object>> data) throws IOException {
+
+        setResponse(response, fileName);
+
+        //导出
+        EasyExcel.write(response.getOutputStream())
+                .head(heads)
+                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                .registerWriteHandler(defaultStylePolicyPolicy())
+                .sheet()
+                .doWrite(data);
+    }
+
+    /**
+     * 导出失败返回错误模板
+     *
+     * @param response 响应对象
+     * @param pathName 模板路径
+     * @param msg      异常消息
+     * @throws IOException
+     */
+    public static void exportError(HttpServletResponse response, String pathName, String msg) throws IOException {
+
+        setResponse(response, "导出失败");
+
+        InputStream resourceAsStream = EasyExcelUtils.class.getResourceAsStream(pathName);
+
+        Map<String, String> map = new HashMap<>();
+        map.put("msg", msg);
+
+        //导出
+        EasyExcel.write(response.getOutputStream()).withTemplate(resourceAsStream).sheet().doFill(map);
+
+    }
+
+    /**
+     * EasyExce导出Excel到多Sheet表 -> 浏览器
+     *
+     * @param fileName                文件名
+     * @param response                响应对象
+     * @param sheetNameList           已经排序过的sheet名称列表
+     * @param data                    数据集 key为sheet名称,value为数据集合
+     * @param clazz                   实体类模板
+     * @param excludeColumnFieldNames 忽略指定列导出根据字段名
+     * @throws IOException
+     */
+    public static <T> void exportToMultipleSheets(String fileName, HttpServletResponse response, List<String> sheetNameList, Map<String, List<T>> data, Class<T> clazz, List<String> excludeColumnFieldNames) throws IOException {
+
+        setResponse(response, fileName);
+
+        // 创建ExcelWriter对象
+        ExcelWriter writer = EasyExcel
+                .write(response.getOutputStream())
+                .registerWriteHandler(new CustomCellWriteWidthConfig()) /*自适应列宽*/
+                .registerWriteHandler(new CustomCellWriteHeightConfig()) /*自适应行高(根据自己情况选择使用,我这里没用到)*/
+                //自定义样式
+                .registerWriteHandler(EasyExcelUtils.defaultStylePolicyPolicy())
+                .build();
+
+        //创建工作表
+        sheetNameList.forEach(sheetName -> {
+            WriteSheet sheet = EasyExcel.writerSheet(sheetName).excludeColumnFieldNames(excludeColumnFieldNames).head(clazz).build();
+            List<T> valueList = data.get(sheetName);
+            if (CollUtil.isEmpty(valueList)) throw new RuntimeException("查询不到对应sheet数据,请检查数据!");
+            writer.write(valueList, sheet);
+
+        });
+
+        //导出
+        writer.finish();
+    }
+
+    /**
+     * 设置响应对象
+     *
+     * @param response
+     * @param fileName
+     */
+    private static void setResponse(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
+        response.setContentType("application/vnd.ms-excel");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20") + ".xlsx");
+    }
+
+    /**
+     * 获取标题和数据
+     * 标题  listTitle
+     * 数据  listBody
+     *
+     * @param file 文件
+     * home.php?mod=space&uid=155549 返回包含标题和数据的Map
+     * @throws IOException 当发生I/O错误时抛出
+     */
+    public static Map<String, Object> readExcelTitleAndBody(MultipartFile file) throws IOException {
+        InputStream inputStream = file.getInputStream();
+        List<String> listTitle = new ArrayList<>(4);
+        List<Map<String, String>> listBody = new ArrayList<>();
+
+        Integer count = 0;
+        AnalysisEventListener<Map<Integer, String>> listener = new AnalysisEventListener<Map<Integer, String>>() {
+            @Override
+            public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
+                // 在这里处理标题行的数据
+                // headMap是一个Map,键为列的索引,值为列的标题
+                // 你可以在这里获取到标题行的数据
+                if (listTitle.size() == 0) {
+                    headMap.forEach((k, v) -> {
+                        listTitle.add(v);
+                    });
+                }
+            }
+
+            @Override
+            public void invoke(Map<Integer, String> data, AnalysisContext context) {
+                // 这里是读取到每一行数据时的处理逻辑
+                Map<String, String> map = new HashMap<>();
+                data.forEach((k, v) -> {
+                    map.put(listTitle.get(k), v);
+                });
+                listBody.add(map);
+            }
+
+            @Override
+            public void doAfterAllAnalysed(AnalysisContext context) {
+                // 读取完成后的处理逻辑
+            }
+        };
+
+        EasyExcel.read(inputStream, listener).sheet().doRead();
+        inputStream.close();
+        Map<String, Object> resMap = new HashMap<>();
+        resMap.put("listTitle", listTitle);
+        resMap.put("listBody", listBody);
+        // 返回标题行的数据
+        return resMap;
+    }
+
+    /**
+     * 默认样式策略策略
+     *
+     * @return
+     */
+    public static HorizontalCellStyleStrategy defaultStylePolicyPolicy() {
+        // 头的策略
+        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
+        //设置列宽
+        // 背景设置为浅蓝色
+        headWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
+        //设置水平对齐方式
+        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
+        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+
+        //设置字体为微软雅黑
+        WriteFont headWriteFont = new WriteFont();
+        headWriteFont.setFontName("宋体");
+        headWriteCellStyle.setWriteFont(headWriteFont);
+
+        // 内容的策略
+        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
+        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
+        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+
+        //设置字体为微软雅黑
+        WriteFont contentWriteFont = new WriteFont();
+        contentWriteFont.setFontName("宋体");
+        contentWriteCellStyle.setWriteFont(contentWriteFont);
+
+        // 这个策略是 头是头的样式 内容是内容的样式
+        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
+    }
+
+    /**
+     * 通用xlsx模板下载
+     *
+     * @param response
+     * @param fileName
+     */
+    public static void templateDownload(HttpServletResponse response, String fileName) {
+        response.setCharacterEncoding("utf-8");
+        response.setContentType("text/html;charset=utf-8");
+        response.setContentType("multipart/form-data");
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        try {
+            InputStream inputStream = EasyExcelUtils.class.getResourceAsStream("/static/template/" + fileName);
+            if (inputStream == null) {
+                return;
+            }
+            OutputStream os = response.getOutputStream();
+            byte[] b = new byte[2048];
+            int length;
+            while ((length = inputStream.read(b)) > 0) {
+                os.write(b, 0, length);
+            }
+            os.close();
+            inputStream.close();
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+}
+
+/**
+ * 自适应列宽
+ */
+class CustomCellWriteWidthConfig extends AbstractColumnWidthStyleStrategy {
+
+    private final Map<String, Map<Integer, Integer>> CACHE = new HashMap<>();
+
+    @Override
+    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer integer, Boolean isHead) {
+        boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
+        if (needSetWidth) {
+            Map<Integer, Integer> maxColumnWidthMap = CACHE.computeIfAbsent(writeSheetHolder.getSheetName() + writeSheetHolder.getSheetNo(), k -> new HashMap<>());
+
+            Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
+            // 单元格文本长度大于60换行
+            if (columnWidth >= 0) {
+                if (columnWidth > 60) {
+                    columnWidth = 60;
+                }
+                Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
+                if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
+                    maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
+                    Sheet sheet = writeSheetHolder.getSheet();
+                    sheet.setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
+                }
+            }
+        }
+    }
+
+    /**
+     * 计算长度
+     *
+     * @param cellDataList
+     * @param cell
+     * @param isHead
+     * @return
+     */
+    private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
+        if (isHead) {
+            return cell.getStringCellValue().getBytes().length;
+        } else {
+            CellData<?> cellData = cellDataList.get(0);
+            CellDataTypeEnum type = cellData.getType();
+            if (type == null) {
+                return -1;
+            } else {
+                switch (type) {
+                    case STRING:
+                        // 换行符(数据需要提前解析好)
+                        int index = cellData.getStringValue().indexOf("\n");
+                        return index != -1 ?
+                                cellData.getStringValue().substring(0, index).getBytes().length + 1 : cellData.getStringValue().getBytes().length + 1;
+                    case BOOLEAN:
+                        return cellData.getBooleanValue().toString().getBytes().length;
+                    case NUMBER:
+                        return cellData.getNumberValue().toString().getBytes().length;
+                    default:
+                        return -1;
+                }
+            }
+        }
+    }
+}
+
+/**
+ * 自适应行高
+ */
+class CustomCellWriteHeightConfig extends AbstractRowHeightStyleStrategy {
+    /**
+     * 默认高度
+     */
+    private static final Integer DEFAULT_HEIGHT = 300;
+
+    @Override
+    protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
+    }
+
+    @Override
+    protected void setContentColumnHeight(Row row, int relativeRowIndex) {
+        Iterator<Cell> cellIterator = row.cellIterator();
+        if (!cellIterator.hasNext()) {
+            return;
+        }
+        // 默认为 1行高度
+        int maxHeight = 1;
+        while (cellIterator.hasNext()) {
+            Cell cell = cellIterator.next();
+            if (cell.getCellTypeEnum() == CellType.STRING) {
+                String value = cell.getStringCellValue();
+                int len = value.length();
+                int num = 0;
+                if (len > 50) {
+                    num = len % 50 > 0 ? len / 50 : len / 2 - 1;
+                }
+                if (num > 0) {
+                    for (int i = 0; i < num; i++) {
+                        value = value.substring(0, (i + 1) * 50 + i) + "\n" + value.substring((i + 1) * 50 + i, len + i);
+                    }
+                }
+                if (value.contains("\n")) {
+                    int length = value.split("\n").length;
+                    maxHeight = Math.max(maxHeight, length) + 1;
+                }
+            }
+        }
+        row.setHeight((short) ((maxHeight) * DEFAULT_HEIGHT));
+    }
+
+}
+
+/**
+ * 合并行策略
+ */
+class MergeRowStrategy implements RowWriteHandler {
+
+    /**
+     * 需要合并的依据的列下表数组(从 0 开始),例如传{1,2}则判断第二列和第三列是否相同,相同则合并mergeColumnIndexList对应列
+     */
+    private final int[] mergeByColumn;
+    /**
+     * 需合并的列下标数组(从 0 开始)
+     */
+    private final int[] mergeColumnIndexList;
+
+    /**
+     * 是否清空冗余内容
+     */
+    private boolean isCleanSurplusContent = true;
+
+    /**
+     * 合并 Key
+     */
+    private String mergeKey = null;
+    /**
+     * 合并起始行下标
+     */
+    private int mergeStartRowIndex;
+
+    /**
+     * @param mergeByColumn        需要合并的依据的列下表数组
+     * @param mergeColumnIndexList 需合并的列下标数组
+     */
+    public MergeRowStrategy(int[] mergeByColumn, int[] mergeColumnIndexList) {
+
+        this.mergeByColumn = mergeByColumn;
+        this.mergeColumnIndexList = mergeColumnIndexList;
+    }
+
+    @Override
+    public void afterRowDispose(RowWriteHandlerContext context) {
+        if (context.getHead() || context.getRelativeRowIndex() == null) {
+            return;
+        }
+
+        //需要合并的依据组合
+        StringJoiner sj = new StringJoiner("&-&");
+        for (int index : mergeByColumn) {
+            sj.add(context.getRow().getCell(index).getStringCellValue());
+        }
+
+        if (context.getRelativeRowIndex() == 0) {
+            this.mergeKey = sj.toString();
+            this.mergeStartRowIndex = context.getRowIndex();
+            return;
+        }
+
+        String currentKey = sj.toString();
+        if (!Objects.equals(currentKey, this.mergeKey)) {
+            this.mergeKey = currentKey;
+            this.mergeStartRowIndex = context.getRowIndex();
+            return;
+        } else {
+            //清空当前要合并单元格的内容
+            for (Integer index : mergeColumnIndexList) {
+                context.getWriteSheetHolder().getSheet().getRow(context.getRowIndex()).getCell(index).setCellValue("");
+            }
+
+        }
+
+        for (Integer columnIndex : mergeColumnIndexList) {
+            CellRangeAddress cellRangeAddress = new CellRangeAddress(
+                    mergeStartRowIndex,
+                    context.getRowIndex(),
+                    columnIndex,
+                    columnIndex);
+            context.getWriteSheetHolder().getSheet().addMergedRegionUnsafe(cellRangeAddress);
+        }
+    }
+}