#!/usr/bin/env python
# -*- coding:utf-8 -*-
from typing import Dict

import pptx
import copy
import threading
import platform
import os
import clr  # add C# suppor
import gc
from pptx import Presentation
from pptx.util import Cm, Pt, Inches
from pptx.enum.shapes import MSO_SHAPE_TYPE
from pptx.chart.data import CategoryChartData
from pptx.chart.data import XyChartData
from pptx.chart.data import BubbleChartData
from pptx.enum.text import PP_ALIGN
#from pptx.enum.text import MSO_ANCHOR
from pptx.dml.color import RGBColor
from pptx.dml.color import CT_HslColor
from pptx.enum.chart import XL_CHART_TYPE
from datetime import datetime
from core.analysis_chart import *
from shutil import copyfile
from core.AnalysisMongoDetail import *
from pathlib import Path
import xlwings as xw
from operator import *
import jpype
from jpype import *
import zipfile
import shutil
import requests
import urllib.parse
from openpyxl import Workbook
import sys
import subprocess
import redis
from redis.sentinel import Sentinel
import chardet
from nacos_py import *
from wordcloud import WordCloud, ImageColorGenerator
from PIL import Image
from PIL import ImageColor
import concurrent.futures
import savReaderWriter
import multiprocessing


def myReportMain(PlatID, ProjID, TempID, TokenID, mongodb_cfg, caseFilter, fileGroup, fileName, edition, updateFlag,
                 templateFileServerUrl, redis_cfg, updatePhraseFlag, casesCondition):
    lock, fileCount, reportError = threading.Lock(), 0, {}
    if str(os.path.abspath(os.curdir)).find("core") > 0:
        filePath = os.path.abspath(os.curdir).replace("core", "pptx")
    else:
        filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
    fileZipPath = os.path.join(filePath, 'report', datetime.datetime.now().strftime('%Y%m%d%H%M%S%f'))
    isExists = os.path.exists(fileZipPath)
    if not isExists:
        os.makedirs(fileZipPath)
    if ProjID != "1":
        templateDownLoad(ProjID, TempID, edition, TokenID, templateFileServerUrl, reportError)  # 模板下载
    for fileIndex, fileItem in enumerate(fileGroup):
        if casesCondition is None:
            casesCondition = {caseFilter: fileItem}
        else:
            casesCondition[caseFilter] = fileItem
        fileCount += 1
        nowString, targetPath = datetime.datetime.now().strftime('%H%M%S%f'), None
        chartfile, report = str(TempID) + nowString + ".txt", myReportCreate()
        threadReport = threading.Thread(target=report.report,
                                        args=(
                                        PlatID, ProjID, TempID, mongodb_cfg, fileIndex, fileItem, fileName, chartfile,
                                        edition, updateFlag, fileZipPath, redis_cfg, updatePhraseFlag, casesCondition,))
        threadChart = threading.Thread(target=report.chart, args=(chartfile, fileZipPath, lock,))
        threadReport.start()
        threadReport.join()
        threadChart.start()
        if fileCount == len(fileGroup):
            threadChart.join()

    returnFileZipPath = zipDir(fileZipPath)
    if ProjID == "1":
        os.remove(returnFileZipPath)
        return None
    else:
        shutil.rmtree(fileZipPath)
        return returnFileZipPath


def myReportPPTXMainJava(PlatID, ProjID, TempID, TokenID, mongodb_cfg, caseFilter, fileGroup, fileName, edition,
                         updateFlag, templateFileServerUrl, redis_cfg, updatePhraseFlag, casesCondition):
    fileCount, template_file, reportCreate, reportClass = 0, '', True, myReportCreate()
    if str(os.path.abspath(os.curdir)).find("core") > 0:
        filePath = os.path.abspath(os.curdir).replace("core", "pptx")
    else:
        filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
    fileZipPath = os.path.join(filePath, 'report', TempID + datetime.datetime.now().strftime('%Y%m%d%H%M%S%f'))
    isExists = os.path.exists(fileZipPath)
    if not isExists:
        os.makedirs(fileZipPath)

    reportClass.redis_update(TempID, redis_cfg)
    try:
        if ProjID != "1":
            templateDownLoad(ProjID, TempID, edition, TokenID, templateFileServerUrl, reportClass._reportError)  # 模板下载
        fileDle(os.path.join(filePath, 'report'))  # 前一天报告删除
        if fileGroup is None: fileGroup = ['allData']
        for fileIndex, fileItem in enumerate(fileGroup):
            if not os.path.exists(fileZipPath):
                reportCreate = False
                break
            if fileItem == 'allData':
                if casesCondition is None:
                    casesCondition = {'isDeleted': {'$ne': True}}
            else:
                if casesCondition is None:
                    casesCondition = {caseFilter: fileItem}
                else:
                    casesCondition[caseFilter] = fileItem
            fileCount += 1
            nowString, targetPath = datetime.datetime.now().strftime('%H%M%S%f'), None
            chartfile = str(TempID) + nowString + ".txt"
            reportClass.report(PlatID, ProjID, TempID, mongodb_cfg, fileIndex, fileItem, fileName, chartfile, edition,
                               updateFlag, fileZipPath, redis_cfg, updatePhraseFlag, copy.deepcopy(casesCondition))
            if Path(reportClass.returnTargetPath()).is_file() and os.path.exists(fileZipPath):
                reportClass.javaChart(fileIndex, chartfile, fileZipPath, TempID, redis_cfg, len(fileGroup))
                if not os.path.exists(fileZipPath):
                    reportCreate = False
                    break
            else:
                chartJsonPath = os.path.join(filePath, 'charts', chartfile)
                if Path(chartJsonPath).is_file():
                    os.remove(chartJsonPath)
                reportCreate = False
                break
    except Exception as ex:
        reportName, reportStatus = reportClass.redis_get()
        if len(reportName) == 0: reportClass.redis_update(TempID, redis_cfg, '出错')
        ex = FormatErrorCode(ex)
        my_log.error(ex)
    finally:
        if reportCreate:
            returnFileZipPath = zipDir(fileZipPath)
            shutil.rmtree(fileZipPath)
            reportClass.redis_update2(TempID, redis_cfg)
            return returnFileZipPath
        else:
            return None


def myReportName(PlatID, ProjID, TempID, mongodb_cfg, fileName, casesCondition):
    fileCondition, json_data = "", ""
    if casesCondition and str(casesCondition).strip() != '':
        for key, value in casesCondition.items():
            fileCondition = fileCondition + value

    while json_data == "":
        json_data_mongo = mongo_analysis_select(PlatID, mongodb_cfg, ProjID, TempID, fileName + fileCondition)
        for json_data_mongo_item in json_data_mongo:
            json_data = json_data_mongo_item["json_data"]
        time.sleep(3)
        print(fileName)
    return None


class myReportCreate:
    def __init__(self):
        self._targetPath = None
        self._targetPathNew = None
        self._conditionReplace = None
        self._tableHead = None
        self._rowDelete = None
        self._replaceText = None
        self._replaceChart = None
        self._reportName = []
        self._reportStatus = []
        self._slideDelete = None
        self._reportError = {}
        # self._JDClass = JDClass

    def report(self, PlatID, ProjID, TempID, mongodb_cfg, fileIndex, fileItem, fileName, chartfile, edition, updateFlag,
               fileZipPath, redis_cfg, updatePhraseFlag, Condition):
        wordflag, documentPptx, targetPath, filePath, templateError, NewFileName, fileCondition, dataSetIdFlag = \
            False, None, None, "", "相关模板未设定", "", "", {}
        self._reportName.append(fileItem)
        self._reportStatus.append('')
        try:
            if Condition and str(Condition).strip() != '':
                for key, value in Condition.items():
                    if value != fileItem and key != 'isDeleted':
                        fileCondition = fileCondition + str(value)
            else:
                Condition = None
            templateData = mongo_template_logic(PlatID, mongodb_cfg, ProjID, TempID)
            # templateCount = mongo_template_logic(PlatID, ProjID, TempID)
            if templateData is not None:
                if str(os.path.abspath(os.curdir)).find("core") > 0:
                    filePath = os.path.abspath(os.curdir).replace("core", "pptx")
                else:
                    filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
                sourcefile, nowString = TempID + edition + ".pptx", datetime.datetime.now().strftime('%H%M%S%f')
                targetfile = str(TempID) + nowString + ".pptx"
                sourcePath = os.path.join(filePath, 'template', sourcefile)
                targetPath = os.path.join(filePath, 'report', targetfile)
                my_file = Path(sourcePath)
                if my_file.is_file():
                    my_file = Path(targetPath)
                    if my_file.is_file():
                        os.unlink(targetPath)
                    copyfile(sourcePath, targetPath)
                    if fileName.find("XXX") > -1:
                        self._reportName[fileIndex] = fileName.replace("XXX", fileItem)
                    else:
                        self._reportName[fileIndex] = fileItem + fileName
                    self._reportStatus[fileIndex] = '计算'
                    self.redis_update(TempID, redis_cfg)
                    templateError = ""
                    for templateItem in templateData:
                        template = templateItem["template"]
                        for rowItem in template:
                            if rowItem["type"] == "title":
                                pass
                            elif rowItem["type"] == "paragraph":
                                pass
                            elif rowItem["type"] == "catalog":
                                pass
                            elif rowItem["type"] == "separator":
                                pass
                            elif rowItem["type"] == "text":
                                if "replace" in rowItem.keys():
                                    for replaceItem in rowItem["replace"]:
                                        replaceFlag = False
                                        for keyCondition, valueCondition in Condition.items():
                                            if valueCondition in replaceItem["condition"]:
                                                replaceFlag = True
                                                break
                                        if replaceFlag:
                                            self._replaceText = replaceItem["replace"]
                            elif rowItem["type"] == "table":
                                if "replace" in rowItem.keys():
                                    replace, cell, content, position, self._tableHead = \
                                        rowItem["replace"], [], [], [], {}
                                    for replaceItem in replace:
                                        replaceFlag = False
                                        for keyCondition, valueCondition in Condition.items():
                                            if valueCondition in replaceItem["condition"]:
                                                replaceFlag = True
                                                break
                                        if replaceFlag:
                                            cell.append(replaceItem["cell"])
                                            content.append(str(replaceItem["content"]).strip())
                                            if str(replaceItem["position"]).find("表") >= 0:
                                                position.append(str(replaceItem["position"]).strip())
                                            else:
                                                position.append("[表" + str(replaceItem["position"]).strip() + "]")
                                    if len(cell) > 0:
                                        self._tableHead["cell"] = cell
                                        self._tableHead["content"] = content
                                        self._tableHead["position"] = position
                                    else:
                                        self._tableHead = None
                            elif rowItem["type"] == "condition":
                                json_data, json_data_flag = {}, True
                                if "analy" in rowItem.keys():
                                    analysis = rowItem["analy"]
                                    json_data, json_data_flag = \
                                        myAnalysis(PlatID, ProjID, mongodb_cfg, analysis, copy.deepcopy(Condition),
                                                   None, "", "", fileZipPath, {}, self._reportError)
                                if "content" in rowItem.keys():
                                    content, self._conditionReplace = rowItem["content"], [[], []]
                                    for contentRow in content:
                                        if contentRow["type"] == "replace":
                                            self._conditionReplace[1].append(copy.deepcopy(contentRow["replaceFrom"]))
                                            replaceFrom = contentRow["replaceFrom"]
                                            if str(contentRow["replaceTo"]).find("data") > -1 and \
                                                    str(contentRow["replaceTo"]).find(":") > -1:
                                                replaceToData = str(contentRow["replaceTo"]).split(':')
                                                datasource = json.loads(json_data[replaceToData[0]])
                                                datasource["detailValid"].sort(key=lambda x: x["validpercent"],
                                                                               reverse=True)
                                                if len(datasource["detailValid"]) > 0:
                                                    valueIndex = 0
                                                    for keyWords, valueWords in replaceFrom.items():
                                                        if str(valueWords).find("max") > -1 and \
                                                                str(valueWords).strip()[-1] != 'x' and \
                                                                is_number(str(valueWords).strip()[-1]):
                                                            valueIndex = int(str(valueWords).strip()[-1]) - 1
                                                        if check_json_format(json.dumps(valueWords)):
                                                            for keyWordsItem, valueWordsItem in valueWords.items():
                                                                if str(valueWordsItem).find("max") > -1 and \
                                                                        str(valueWordsItem).strip()[-1] != 'x' and \
                                                                        is_number(str(valueWordsItem).strip()[-1]):
                                                                    valueIndex = int(
                                                                        str(valueWordsItem).strip()[-1]) - 1
                                                                replaceFrom[keyWords] = \
                                                                    {keyWordsItem: str(datasource["detailValid"]
                                                                                       [valueIndex][replaceToData[1]])}
                                                        else:
                                                            replaceFrom[keyWords] = \
                                                                str(datasource["detailValid"][valueIndex][
                                                                        replaceToData[1]])
                                            else:
                                                if "condition" in contentRow.keys():
                                                    for keyCondition, valueCondition in Condition.items():
                                                        if valueCondition in contentRow["condition"]:
                                                            for keyWords, valueWords in replaceFrom.items():
                                                                replaceFrom[keyWords] = str(contentRow["replaceTo"])
                                                else:
                                                    for keyWords, valueWords in replaceFrom.items():
                                                        replaceFrom[keyWords] = str(contentRow["replaceTo"])
                                            self._conditionReplace[0].append(replaceFrom)
                                        if contentRow["type"] == "fileReplace":
                                            fileReplace, fileReplaceName = str(contentRow["replace"]).split('&'), ""
                                            for fileReplaceItem in fileReplace:
                                                if str(fileReplaceItem).find("data") > -1 and \
                                                        str(fileReplaceItem).find(":") > -1:
                                                    replaceData = str(fileReplaceItem).split(':')
                                                    datasource = json.loads(json_data[replaceData[0]])
                                                    if len(datasource["detailValid"]) > 0:
                                                        fileReplaceName = \
                                                            fileReplaceName + \
                                                            str(datasource["detailValid"][0][replaceData[1]]).strip()
                                                else:
                                                    fileReplaceName = fileReplaceName + str(fileReplaceItem).strip()
                                            if fileItem != 'allData': fileItem = fileReplaceName
                                        if contentRow["type"] == "chartReplace":
                                            chartReplace, fileReplaceName = contentRow["replace"], ""
                                            for chartReplaceIndex, chartReplaceItem in enumerate(chartReplace[1]):
                                                if str(chartReplaceItem).find("data") > -1 and \
                                                        str(chartReplaceItem).find(":") > -1:
                                                    replaceData = str(chartReplaceItem).split(':')
                                                    datasource = json.loads(json_data[replaceData[0]])
                                                    if len(datasource["detailValid"]) > 0:
                                                        chartReplace[1][chartReplaceIndex] = \
                                                            str(datasource["detailValid"][0][replaceData[1]]).strip()
                                            self._replaceChart = chartReplace
                                if "rowDelete" in rowItem.keys():
                                    for keyCondition, valueCondition in Condition.items():
                                        if valueCondition in rowItem["rowDelete"]:
                                            self._rowDelete = True
                            elif rowItem["type"] == "analy":
                                analysis, content, json_data, json_data_flag, json_data_save = \
                                    rowItem["analy"], rowItem["content"], None, True, True
                                if fileName.find("XXX") > -1:
                                    self._reportName[fileIndex] = fileName.replace("XXX", fileItem)
                                else:
                                    self._reportName[fileIndex] = fileItem + fileName
                                self._reportStatus[fileIndex] = '计算'
                                self.redis_update(TempID, redis_cfg)
                                if myTemplateCheck(PlatID, ProjID, TempID, mongodb_cfg, analysis) or updateFlag:
                                    if updateFlag:
                                        mongo_analysis_delete(PlatID, mongodb_cfg, ProjID, TempID)
                                    else:
                                        json_data_mongo = mongo_analysis_select(PlatID, mongodb_cfg, ProjID, TempID,
                                                                                fileItem + fileCondition)
                                        for json_data_mongo_item in json_data_mongo:
                                            json_data = json_data_mongo_item["json_data"]
                                    json_data_save = False
                                    if json_data is None:
                                        '''
                                        json_data, json_data_flag = myAnalysis(PlatID, ProjID, mongodb_cfg, analysis,
                                                                               Condition, self._conditionReplace,
                                                                               self._rowDelete, TempID)
                                        '''
                                        dataSetIdFlag, analysisThreadFlag = \
                                            myDataSetId(PlatID, ProjID, mongodb_cfg, analysis, dataSetIdFlag)
                                        if analysisThreadFlag:
                                            json_data, json_data_flag = myAnalysisThread \
                                                (PlatID, ProjID, mongodb_cfg, analysis, Condition,
                                                 self._conditionReplace,
                                                 self._rowDelete, TempID, fileZipPath, dataSetIdFlag, self._reportError)
                                            if json_data: json_data = myJson_data_reset(json_data)
                                        else:
                                            json_data, json_data_flag = myAnalysis \
                                                (PlatID, ProjID, mongodb_cfg, analysis, Condition,
                                                 self._conditionReplace,
                                                 self._rowDelete, TempID, fileZipPath, dataSetIdFlag, self._reportError)
                                        json_data_save = True
                                else:
                                    dataSetIdFlag, analysisThreadFlag = \
                                        myDataSetId(PlatID, ProjID, mongodb_cfg, analysis, dataSetIdFlag)
                                    if analysisThreadFlag:
                                        json_data, json_data_flag = myAnalysisThread \
                                            (PlatID, ProjID, mongodb_cfg, analysis, Condition, self._conditionReplace,
                                             self._rowDelete, TempID, fileZipPath, dataSetIdFlag, self._reportError)
                                        if json_data: json_data = myJson_data_reset(json_data)
                                    else:
                                        json_data, json_data_flag = myAnalysis \
                                            (PlatID, ProjID, mongodb_cfg, analysis, Condition, self._conditionReplace,
                                             self._rowDelete, TempID, fileZipPath, dataSetIdFlag, self._reportError)
                                    analysisJson = dict(platId=PlatID, projId=ProjID, tempId=TempID,
                                                        reportId=fileItem + fileCondition, json_data=json_data)
                                    if json_data and json_data_flag: mongo_analysis_insert(mongodb_cfg, analysisJson)
                                if json_data and json_data_flag:
                                    if json_data_save:
                                        analysisJson = dict(platId=PlatID, projId=ProjID, tempId=TempID,
                                                            reportId=fileItem + fileCondition, json_data=json_data)
                                        mongo_analysis_insert(mongodb_cfg, analysisJson)
                                    myTemplateUpdate(PlatID, ProjID, TempID, mongodb_cfg, template)
                                if json_data:
                                    self._reportStatus[fileIndex] = '报告'
                                    self.redis_update(TempID, redis_cfg)
                                    documentPptx = Presentation(targetPath)
                                    self._slideDelete = myReport(documentPptx, content, json_data, chartfile,
                                                                 self._tableHead,self._replaceText, self._replaceChart,
                                                                 fileZipPath, edition, TempID, updatePhraseFlag,
                                                                 self._reportError)
                    if os.path.exists(fileZipPath): wordflag = True
                else:
                    raise MyCustomError(retcode=6001)
        except Exception as ex:
            self._reportError['reportStart'] = str(ex)
            self._reportStatus[fileIndex] = '出错'
            self.redis_update(TempID, redis_cfg)
            ex = FormatErrorCode(ex)
            my_log.error(ex)
        finally:
            if wordflag:
                if fileItem == 'allData':
                    if fileName.find("XXX") > -1:
                        NewFileName = fileName.replace("XXX", '')
                    else:
                        NewFileName = fileName
                else:
                    if fileName.find("XXX") > -1:
                        NewFileName = fileName.replace("XXX", fileItem)
                    else:
                        NewFileName = fileItem + fileName
                if documentPptx is not None: documentPptx.save(targetPath)
                if platform.system() == 'Windows':
                    tmp = os.popen("ps -af").read()
                    word_count = tmp.count('pptx')
                    if word_count > 0:
                        os.system("killall -9 pptx")
                if NewFileName and NewFileName.split() != "":
                    dirname, filename = os.path.split(targetPath)
                    filename, extension = os.path.splitext(filename)
                    extension = extension + templateError
                    new_targetPath = os.path.join(dirname, NewFileName + extension)
                    my_file = Path(new_targetPath)
                    if my_file.is_file():
                        new_targetPath = os.path.join(dirname, filename + NewFileName + extension)
                    self._targetPathNew = new_targetPath
        self._targetPath = targetPath
        try:
            for x in locals().keys():
                del locals()[x]
            gc.collect()
        except Exception as e:
            pass

    def chart(self, chartfile, fileZipPath, lock):
        lock.acquire()
        if str(os.path.abspath(os.curdir)).find("core") > 0:
            filePath = os.path.abspath(os.curdir).replace("core", "pptx")
        else:
            filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
        chartJsonPath = os.path.join(filePath, 'charts', chartfile)
        if platform.system() == 'Windows' and os.path.exists(chartJsonPath):
            try:
                # clr.AddReference("WordChartHelper")
                # clr.FindAssembly('WordChartHelper')
                import WordChartHelper
                chart = WordChartHelper.WordChartHelper()
                chart.ChartCreate(chartJsonPath, self._targetPath)
            except Exception as ex:
                pass
            finally:
                if self._targetPathNew is not None:
                    os.rename(self._targetPath, self._targetPathNew)
                    self._targetPath = self._targetPathNew
                os.remove(chartJsonPath)
                shutil.move(self._targetPath, fileZipPath)
        lock.release()
        try:
            for x in locals().keys():
                del locals()[x]
            gc.collect()
        except Exception as e:
            pass

    def javaChart(self, fileIndex, chartfile, fileZipPath, TempID, redis_cfg, fileMax):
        if str(os.path.abspath(os.curdir)).find("core") > 0:
            filePath = os.path.abspath(os.curdir).replace("core", "pptx")
            chartPath = os.path.join(os.path.abspath(os.curdir), "ReportChartReplace-1.0-SNAPSHOT.jar")
        else:
            filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
            chartPath = os.path.join(os.path.abspath(os.curdir), "core", "ReportChartReplace-1.0-SNAPSHOT.jar")
        self._reportStatus[fileIndex] = '图表'
        self.redis_update(TempID, redis_cfg)
        chartJsonPath = os.path.join(filePath, 'charts', chartfile)
        logFilePath = os.path.join(filePath, 'charts', datetime.datetime.now().strftime('%H%M%S%f') + '.txt')
        repeatFlag = fileRepeat(self._targetPath, fileZipPath)
        if os.path.exists(chartJsonPath):
            try:
                command = "java -jar " + chartPath
                cmd = [command, self._targetPath, chartJsonPath, logFilePath, fileZipPath]
                new_cmd = " ".join(cmd)
                print(new_cmd)
                stdout, stderr = subprocess.Popen(new_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                                  shell=True).communicate()
                # encoding = chardet.detect(stdout)["encoding"]
                # r = stdout.decode(encoding)
            except Exception as ex:
                self._reportError['reportJava'] = str(ex)
                self._reportStatus[fileIndex] = '出错'
                self.redis_update(TempID, redis_cfg)
                my_log.error(ex)
                print(ex)
                pass
            finally:
                if self._targetPathNew is not None:
                    try:
                        os.rename(self._targetPath, self._targetPathNew)
                        self._targetPath = self._targetPathNew
                    except Exception as ex:
                        pass
                deleteSlide(self._targetPath, self._slideDelete)
                if os.path.exists(chartJsonPath): os.remove(chartJsonPath)
                if repeatFlag != '':
                    os.rename(self._targetPath, self._targetPath.replace('.pptx', repeatFlag + '.pptx'))
                    shutil.move(self._targetPath.replace('.pptx', repeatFlag + '.pptx'), fileZipPath)
                else:
                    shutil.move(self._targetPath, fileZipPath)
                if Path(logFilePath).is_file():
                    if self._reportError:
                        with open(logFilePath, "a", encoding="utf-8") as fp:
                            fp.write("\n,\n")  # JSON 数组分隔符
                            fp.write(json.dumps(self._reportError, ensure_ascii=False, indent=4))
                            fp.close()
                    shutil.move(logFilePath, fileZipPath)
                else:
                    if self._reportError:
                        with open(logFilePath, "w", encoding="utf-8") as fp:
                            fp.write(json.dumps(self._reportError, ensure_ascii=False, indent=4))
                            fp.close()
                        shutil.move(logFilePath, fileZipPath)
                if repeatFlag != '':
                    self._reportName[fileIndex] = self._reportName[fileIndex] + repeatFlag
                if fileIndex < fileMax - 1:
                    self._reportStatus[fileIndex] = '完成'
                    self.redis_update(TempID, redis_cfg)
        else:
            if self._targetPathNew is not None:
                os.rename(self._targetPath, self._targetPathNew)
                self._targetPath = self._targetPathNew
            deleteSlide(self._targetPath, self._slideDelete)
            if repeatFlag != '':
                os.rename(self._targetPath, self._targetPath.replace('.pptx', repeatFlag + '.pptx'))
                shutil.move(self._targetPath.replace('.pptx', repeatFlag + '.pptx'), fileZipPath)
            else:
                shutil.move(self._targetPath, fileZipPath)
            if self._reportError:
                with open(logFilePath, "w", encoding="utf-8") as fp:
                    fp.write(json.dumps(self._reportError, ensure_ascii=False, indent=4))
                    fp.close()
                shutil.move(logFilePath, fileZipPath)
            if repeatFlag != '':
                self._reportName[fileIndex] = self._reportName[fileIndex] + repeatFlag
            if fileIndex < fileMax - 1:
                self._reportStatus[fileIndex] = '完成'
                self.redis_update(TempID, redis_cfg)

    def redis_update2(self, TempID, redis_cfg):
        try:
            reportNameDict = {}
            for reportIndex, reportItem in enumerate(self._reportName):
                reportNameDict[reportItem] = '完成'
            reportName = json.dumps(reportNameDict, ensure_ascii=False)
            if 'redis_connect' not in redis_cfg.keys():
                if str(redis_cfg['host']).find(',') > -1:
                    host_list = str(redis_cfg['host']).split(',')
                    port_list = str(redis_cfg['port']).split(',')
                    host_port_list = []
                    for host_list_index, host_list_item in enumerate(host_list):
                        if host_list_index < len(port_list):
                            host_port_list.append((host_list_item, int(port_list[host_list_index])))
                        else:
                            host_port_list.append((host_list_item, int(port_list[0])))
                    sentinel = Sentinel(host_port_list)
                    master = sentinel.master_for(redis_cfg['mymaster'], socket_timeout=1000,
                                                 password=redis_cfg['password'])
                    master.set(redis_cfg['namespace'] + ':' + TempID, reportName)
                else:
                    r = redis.Redis(host=redis_cfg['host'], port=redis_cfg['port'], password=redis_cfg['password'],
                                    decode_responses=True)
                    r.set(redis_cfg['namespace'] + ':' + TempID, reportName)
            else:
                redis_connect = redis_cfg['redis_connect']
                redis_connect.set(redis_cfg['namespace'] + ':' + TempID, reportName)
        except Exception as ex:
            print(ex)

    def redis_update(self, TempID, redis_cfg, errorMessage=None):
        try:
            if len(self._reportName) == 0:
                if errorMessage is None:
                    reportName = '报告生成中'
                else:
                    reportName = errorMessage
            else:
                reportNameDict = {}
                for reportIndex, reportItem in enumerate(self._reportName):
                    reportNameDict[reportItem] = self._reportStatus[reportIndex]
                reportName = json.dumps(reportNameDict, ensure_ascii=False)

            if 'redis_connect' not in redis_cfg.keys():
                if str(redis_cfg['host']).find(',') > -1:
                    host_list = str(redis_cfg['host']).split(',')
                    port_list = str(redis_cfg['port']).split(',')
                    host_port_list = []
                    for host_list_index, host_list_item in enumerate(host_list):
                        if host_list_index < len(port_list):
                            host_port_list.append((host_list_item, int(port_list[host_list_index])))
                        else:
                            host_port_list.append((host_list_item, int(port_list[0])))
                    sentinel = Sentinel(host_port_list)
                    master = sentinel.master_for(redis_cfg['mymaster'], socket_timeout=1000,
                                                 password=redis_cfg['password'])
                    master.set(redis_cfg['namespace'] + ':' + TempID, reportName)
                else:
                    r = redis.Redis(host=redis_cfg['host'], port=redis_cfg['port'], password=redis_cfg['password'],
                                    decode_responses=True)
                    r.set(redis_cfg['namespace'] + ':' + TempID, reportName)
            else:
                redis_connect = redis_cfg['redis_connect']
                redis_connect.set(redis_cfg['namespace'] + ':' + TempID, reportName)
        except Exception as ex:
            print(ex)

    def returnTargetPath(self):
        return self._targetPath

    def redis_get(self):
        return self._reportName, self._reportStatus


def zipDir(dirPath):
    """
    压缩指定文件夹
    :param dirPath: 目标文件夹路径
    """
    outFullName = ""
    try:
        outFullName = dirPath + '.zip'
        zip = zipfile.ZipFile(outFullName, "w", zipfile.ZIP_DEFLATED)
        for path, dirNames, fileNames in os.walk(dirPath):
            for filename in fileNames:
                zip.write(os.path.join(path, filename), filename)
        zip.close()

    except Exception as ex:
        pass
    finally:
        return outFullName


def fileDle(dirPath):
    reportList = os.listdir(dirPath)
    templateList = os.listdir(dirPath.replace('/report', '/charts'))
    today = datetime.datetime.now()
    offset = datetime.timedelta(days=-3)
    todayDelete = str((today + offset).strftime('%Y%m%d%H%M%S%f'))[0:8]
    try:
        for reportItem in reportList:
            f_path = os.path.join(dirPath, reportItem)
            if os.path.isdir(f_path):
                pass
            else:
                if str(reportItem).find('.zip') > 0:
                    if int(str(reportItem)[24:32]) < int(todayDelete):
                        os.remove(f_path)
        for templateItem in templateList:
            t_path = os.path.join(dirPath, templateItem)
            if os.path.isdir(t_path):
                pass
            else:
                if str(templateItem).find('.txt') > 0 and len(str(templateItem)) > 30:
                    os.remove(t_path)
    except Exception as e:
        pass


def fileRepeat(targetPath, dirPath):
    repeatCount = 0
    reportList = os.listdir(dirPath)
    dirName, fileName = os.path.split(targetPath)
    for reportIndex in range(len(reportList)):
        if reportIndex == 0:
            if fileName in reportList:
                repeatCount += 1
        else:
            if fileName.replace('.pptx', '') + str(reportIndex) + '.pptx' in reportList:
                repeatCount += 1
    if repeatCount == 0:
        return ''
    else:
        return str(repeatCount)


def templateDownLoad(ProjID, tempID, templateEdition, tokenID, templateFileServerUrl, reportError):
    if str(os.path.abspath(os.curdir)).find("core") > 0:
        filePath = os.path.abspath(os.curdir).replace("core", "pptx")
    else:
        filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
    targetfile = str(tempID) + templateEdition + ".pptx"
    sourcePath = os.path.join(filePath, 'template', targetfile)
    targetfilePng = str(tempID) + templateEdition + ".png"
    sourcePathPng = os.path.join(filePath, 'template', targetfilePng)
    my_file = Path(sourcePath)
    if my_file.is_file():
        os.remove(sourcePath)

    try:
        query = {"templateId": str(tempID), "edition": templateEdition}
        if templateFileServerUrl != "":
            url = str(templateFileServerUrl).strip() + '/report/downloadReportTemplateWord'
        else:
            url = 'http://192.168.2.160:8851/report/downloadReportTemplateWord'
        url = url + '?' + urllib.parse.urlencode(query)
        # query = {"templateId": "627ba654a517907d77fdaf91", "edition": templateEdition}
        # url = 'https://medudata.bjmu.edu.cn/api/project/report/downloadReportTemplateWord/' + str(ProjID) + '?' + \
        #      urllib.parse.urlencode(query)
        print(url)
        if tokenID != "":
            headers = {'Authorization': 'token = ' + tokenID}
            r = requests.post(url, headers=headers)
        else:
            r = requests.post(url)
        with open(sourcePath, "wb") as code:
            code.write(r.content)
        try:
            queryPng = {"templateId": str(tempID), "edition": templateEdition + "png"}
            if templateFileServerUrl != "":
                url = str(templateFileServerUrl).strip() + '/report/downloadReportTemplateWord'
            else:
                url = 'http://192.168.2.160:8851/report/downloadReportTemplateWord'
            url = url + '?' + urllib.parse.urlencode(queryPng)

            if tokenID != "":
                headers = {'Authorization': 'token = ' + tokenID}
                r = requests.post(url, headers=headers)
            else:
                r = requests.post(url)
            if r.text != '':
                if Path(sourcePathPng).is_file():
                    os.remove(sourcePathPng)
                with open(sourcePathPng, "wb") as code:
                    code.write(r.content)
        except Exception as ex:
            reportError['templateDownLoad'] = str(ex)
            pass
        return True
    except Exception as ex:
        print(ex)
        reportError['templateDownLoad'] = str(ex)
        return False
    finally:
        pass


def caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow, noCondition, json_data, replaceCondition):
    case, keys, values, equalRange = None, [], [], ""
    if "equalRange" in analysisRow.keys():
        equalRange = analysisRow["equalRange"]
    if Condition is not None and isinstance(Condition, dict):
        for key, value in Condition.items():
            if check_json_format(json.dumps(value)):
                for keyWords, valueWords in value.items():
                    if str(keyWords).strip() == "lte" or str(keyWords).strip() == "gte" or \
                            str(keyWords).strip() == "gt" or str(keyWords).strip() == "lt" or \
                            str(keyWords).strip() == "nin" or str(keyWords).strip() == "in" or \
                            str(keyWords).strip() == "regex" or str(keyWords).strip() == "ne":
                        keyWords = "$" + str(keyWords).strip()
                        Condition[key] = {keyWords: valueWords}
    copyCondition = copy.deepcopy(Condition)
    if str(analysisRow["index"]) == "355":
        testFlag = True
    if Condition and noCondition == "":
        if "condition" in analysisRow and json.dumps(analysisRow["condition"]) != "":
            count, value = 0, ""
            datasource = mongo_condition_logic(PlatID, mongodb_cfg, ProjID, analysisRow["dataSourceId"],
                                               str(analysisRow["condition"]).strip(), json.dumps(Condition))
            for rowItem in datasource:
                if float(rowItem['count']) > count:
                    value = str(rowItem['_id']).strip()
                    count = float(rowItem['count'])
            keys.append(str(analysisRow["condition"]).strip())
            values.append(value)
        else:
            if "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and str(analysisRow["filter"]) != "":
                if isinstance(copyCondition, str) and copyCondition != '': copyCondition = json.loads(copyCondition)
                if len(copyCondition) != 0:
                    for key, value in copyCondition.items():
                        keys.append(key)
                        values.append(value)
            else:
                case = Condition
    if "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and str(analysisRow["filter"]) != "":
        for key, value in analysisRow["filter"].items():
            keys.append(key)
            if replaceCondition is not None:
                for replaceIndex, replaceItem in enumerate(replaceCondition[0]):
                    if {key: value} == replaceCondition[1][replaceIndex]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if key == keyReplace:
                                if isinstance(value, str) and isinstance(valueReplace, str):
                                    value = valueReplace
                                if isinstance(value, dict) and isinstance(valueReplace, dict):
                                    value = valueReplace
            if isinstance(value, str) and str(value).find(':') > -1 and str(value).find('data') > -1:
                dataFrom = str(value).strip().split(':')
                datasource = json.loads(json_data[dataFrom[0]])
                value = datasource["head"][0][dataFrom[1]]
            if check_json_format(json.dumps(value)):
                valueNew = {}
                for keyWords, valueWords in value.items():
                    if str(keyWords).strip() == "lte" or str(keyWords).strip() == "gte" or \
                            str(keyWords).strip() == "gt" or str(keyWords).strip() == "lt" or \
                            str(keyWords).strip() == "nin" or str(keyWords).strip() == "in" or \
                            str(keyWords).strip() == "regex" or str(keyWords).strip() == "ne":
                        if isinstance(valueWords, str) and str(valueWords).find(':') > -1 and \
                                str(valueWords).find('data') > -1:
                            dataFrom = str(valueWords).strip().split(':')
                            datasource = json.loads(json_data[dataFrom[0]])
                            valueWords = datasource["head"][0][dataFrom[1]]
                        if isinstance(equalRange, str) and str(equalRange) != "":
                            equalRangeData = str(equalRange).strip().split(':')
                            if is_number(valueWords) and valueWords - math.floor(valueWords) == 0 and \
                                    keyWords == equalRangeData[0]:
                                keyWords = equalRangeData[1]
                        keyWords = "$" + str(keyWords).strip()
                    valueNew[keyWords] = valueWords
                values.append(valueNew)
            else:
                values.append(value)
    if case is not None:
        keys, values = [], []
        for key, value in case.items():
            keys.append(key)
            values.append(value)
    if 'isDeleted' not in keys:
        keys.append('isDeleted')
        values.append({'$ne': True})
    return copy.deepcopy([keys, values])


def pptxdiscription(documentPptx, contentRow, json_data, discriptionJson, allReplace, textDiscription,
                          tableDiscription, tableIndexDiscription, slideDelete):
    """
    :param json_data:
    :param contentRow:
    :type documentPptx: object
    """
    content = contentRow["content"]
    if "content" in content.keys(): contentFlag = True
    else: contentFlag = False
    text, fromtext, discriptionword, discriptionwordargs, bookMark, style = "", "", [], {}, "", ""
    pointdef = lambda: 2 if "point" not in content.keys() else content["point"]
    pointGroupdef = lambda: "" if "pointGroup" not in content.keys() else str(content["pointGroup"])
    bookMarkdef = lambda: "" if "bookMark" not in content.keys() else content["bookMark"]
    styledef = lambda: "" if "style" not in content.keys() else content["style"]
    unitsdef = lambda: "" if "units" not in content.keys() else content["units"]
    countdef = lambda: 1 if "count" not in content.keys() else int(content["count"])
    titledef = lambda: "" if "title" not in content.keys() else content["title"]
    datadef = lambda: None if "data" not in content.keys() else content["data"]
    rowTextdef = lambda: "" if "rowText" not in content.keys() else content["rowText"]
    sortFirstdef = lambda: [] if "sortFirst" not in content.keys() else content["sortFirst"]
    sortLastdef = lambda: [] if "sortLast" not in content.keys() else content["sortLast"]
    outColumndef = lambda: None if "outColumn" not in content.keys() else content["outColumn"]
    phrasedef = lambda: "" if "phrase" not in content.keys() else content["phrase"]
    wordHeaddef = lambda: "" if "wordHead" not in content.keys() else content["wordHead"]
    phraseDatadef = lambda: "" if "phraseData" not in content.keys() else content["phraseData"]
    replaceTextdef = lambda: "" if "replaceText" not in content.keys() else content["replaceText"]
    bigToSmalldef = lambda: "" if "bigToSmall" not in content.keys() else str(content["bigToSmall"])
    connectordef = lambda: None if not contentFlag or "connector" not in content["content"].keys() \
        else content["content"]["connector"]
    noDescriptiondef = lambda: "此题无相关数据！！！！！" if "noDescription" not in content.keys() else \
        content["noDescription"]
    ai_polishingdef = lambda: "" if "ai_polishing_text" not in content.keys() else str(content["ai_polishing_text"])
    point, units, countbreak, title, dataN, rowText, sortFirst, sortLast, outColumn, phrase, detailValid, columnMax, \
    connector, phraseData, wordHead, pointGroup, topStar, replaceText, equalFlag, bookMark, style, noDescription = \
        pointdef(), unitsdef(), countdef(), titledef(), datadef(), rowTextdef(), sortFirstdef(), sortLastdef(), \
        outColumndef(), phrasedef(), [], 0, connectordef(), phraseDatadef(), wordHeaddef(), pointGroupdef(), \
        0, replaceTextdef(), True, bookMarkdef(), styledef(), noDescriptiondef()
    bigToSmall, ai_polishing = bigToSmalldef(), ai_polishingdef()
    if contentFlag and "bigToSmall" in content["content"].keys():
        bigToSmall = str(content["content"]["bigToSmall"])
    datasource = dict(head=[], detailValid=detailValid)
    if title == '[P5Q1-1]':
        testFlag = True
    if allReplace is not None:
        if isinstance(replaceText, str) and replaceText == "":
            replaceText = allReplace
        else:
            if isinstance(replaceText, list):
                for replace in allReplace[0]:
                    replaceText[0].append(replace)
                for replace in allReplace[1]:
                    replaceText[1].append(replace)
    if isinstance(point, str): point = int(point)
    if dataN is not None or outColumn is not None:
        if isinstance(dataN, list):
            if contentFlag and ("sort" in content["content"].keys() or "compare" in content["content"].keys()):
                datasource = dict(head=[], detailValid=[])
                phrase, analysis, count = content["phrase"], "", 0
                for indexN, itemN in enumerate(dataN):
                    datafrom = json.loads(json_data[itemN])
                    if fromtext != "":
                        fromtext += "-"
                    fromtext += datafrom["head"][0]["variableID"]
                    analysis = datafrom["head"][0]["analysis"]
                    if datafrom["head"][0]["count"] != 0:
                        count += datafrom["head"][0]["count"]
                        if datafrom["head"][0]["analysis"] == "frequency":
                            num, per, groupAll = 0, 0.0, content["group"]
                            for rowItem in datafrom["detailValid"]:
                                for ind, it in enumerate(groupAll):
                                    if float(str(rowItem["value"])) == float(str(it)):
                                        num += int(rowItem["count"])
                                        if pointGroup == "":
                                            per += float(rowItem["validpercent"])
                                        else:
                                            per += float(str(formatdata(float(rowItem["validpercent"]),
                                                                        int(pointGroup) + 2)))
                            datasource["detailValid"].append(dict(value=str(indexN), text=phrase[indexN],
                                                                  count=num, validpercent=per))
                        elif datafrom["head"][0]["analysis"] == "means":
                            datasource['detailValid'].append(dict(valueRow=str(indexN), textRow=phrase[indexN],
                                                                  count=int(datafrom["head"][0]["count"]),
                                                                  average=float(datafrom["head"][0]["average"])))
                if title.strip() != "": fromtext = ""
                if analysis == "frequency":
                    datasource["head"].append(
                        dict(varLabel='', variableID=fromtext, count=count, analysis="frequency"))
                elif analysis == "means":
                    datasource["head"].append(
                        dict(rowVarLabel='', RowID=fromtext, ColumnID='', count=count, analysis="comparemeans"))
            else:
                datasource = json.loads(json_data[content["data"]])
        elif dataN is not None and dataN != "【AI总结】":
            datasource = json.loads(json_data[content["data"]])
        if outColumn is not None and isinstance(outColumn, list) and len(outColumn) > 0:
            count, detailRemove, columnStringBack, compareGroupFlag, wordCloudFlag = 0, [], {}, False, False
            if len(sortFirst) != 0:
                rowNo, sortAll = -99999, sortFirst
            else:
                rowNo, sortAll = 99999, sortLast
            if rowText != "":
                detailValidTotal, sumColumnFlag = rowDataProcess(outColumn, rowText, phrase, "", rowNo, sortAll,
                                                                 json_data, True, phraseData, pointGroup, "")
                countFlag, countTotal, detailValidTotalIndex = False, [], 0
                if len(detailValidTotal) > 1:
                    for detailValidTotalItem in detailValidTotal:
                        if "count" in detailValidTotalItem[0]:
                            countFlag, countItem = True, 0
                            for detailItem in detailValidTotalItem:
                                countItem += detailItem["count"]
                            countTotal.append(countItem)
                        else:
                            countFlag = False
                if countFlag:
                    countCheck = 0
                    for countTotalIndex, countTotalItem in enumerate(countTotal):
                        if countCheck < countTotalItem:
                            countCheck, detailValidTotalIndex = countTotalItem, countTotalIndex
                detailValid = detailValidTotal[detailValidTotalIndex]
                for detailItem in detailValid:
                    if detailItem["columnMax"] > columnMax: columnMax = detailItem["columnMax"]
            else:
                for columnIndex in range(len(outColumn)):
                    detailValid.append(dict(value=int(columnIndex + 1)))
                    if isinstance(outColumn[columnIndex], list):
                        if len(outColumn[columnIndex]) > columnMax: columnMax = len(outColumn[columnIndex])
                        for indexCol in range(len(outColumn[columnIndex])):
                            if outColumn[columnIndex][indexCol].find('wordCloud') > 0: wordCloudFlag = True
                            detailValid = outDataProcess(outColumn[columnIndex][indexCol], indexCol, rowText, phrase,
                                                         json_data, detailValid, columnIndex, True, phraseData,
                                                         pointGroup,
                                                         "", columnStringBack)
                    else:
                        if len(outColumn) > columnMax: columnMax = len(outColumn)
                        if outColumn[columnIndex].find('wordCloud') > 0: wordCloudFlag = True
                        detailValid = outDataProcess(outColumn[columnIndex], columnIndex, rowText, phrase, json_data,
                                                     detailValid, -1, True, phraseData, pointGroup, "",
                                                     columnStringBack)
            if "group" in content.keys() or "group" in content["content"].keys():
                if "group" in content.keys():
                    compareGroup = content["group"]
                else:
                    compareGroup = content["content"]["group"]
                for groupIndex, groupItem in enumerate(compareGroup[1]):
                    if isinstance(groupItem, str) and groupItem == '=':
                        if isinstance(compareGroup[2][groupIndex], str) and compareGroup[2][groupIndex] == '0':
                            compareGroupFlag = True
            if wordCloudFlag:
                detailValidCloud, valueCloudIndex = [], 0
                for keyCloud, valueCloud in detailValid.items():
                    valueCloudIndex += 1
                    detailValidCloud.append(dict(value=valueCloudIndex, text=keyCloud, count=valueCloud,
                                                 validpercent=valueCloud))
                detailValid = detailValidCloud
            else:
                for detailIndex, detailItem in enumerate(detailValid):
                    removeFlag, indexStar = True, 1
                    if rowText != "": indexStar = 0
                    for indexColumn in range(indexStar, columnMax):
                        if (detailItem["column" + str(indexColumn)] is not None and
                            is_number(sort_key(detailItem["column" + str(indexColumn)], None)) and
                            float(str(sort_key(detailItem["column" + str(indexColumn)], None))) != 0.0) or \
                                (str(detailItem["columnName" + str(indexColumn)]).find("text") > -1 and
                                 detailItem["column" + str(indexColumn)] is not None and
                                 detailItem["column" + str(indexColumn)] != ""):
                            removeFlag = False
                        if detailItem["column" + str(indexColumn)] is None:
                            detailValid[detailIndex]["column" + str(indexColumn)] = 0
                            if "columnName" + str(indexColumn) in detailValid[detailIndex].keys():
                                columnNameString = detailValid[detailIndex]["columnName" + str(indexColumn)]
                                if columnNameString in detailValid[detailIndex].keys():
                                    detailValid[detailIndex][columnNameString] = 0
                    if removeFlag and not compareGroupFlag:
                        detailRemove.append(detailItem)
                for detailItem in detailRemove:
                    detailValid.remove(detailItem)
            datasource['detailValid'], count = detailValid, len(detailValid)
            datasource["head"].append(
                dict(varLabel='', variableID="", count=count, analysis="frequency"))
        if isinstance(dataN, str) and dataN == "【AI总结】":
            head = None
        else:
            head = datasource["head"][0]
        if head is not None and \
                (head["count"] == 0 or (head["analysis"] != "means" and len(datasource["detailValid"]) == 0)):
            if str(head["analysis"]) == "crosstabs" or str(head["analysis"]) == "crosstabsMultiple" or \
                    str(head["analysis"]) == "comparemeans" or str(head["analysis"]) == "crosstabsSort":
                if str(head["ColumnID"]).strip() == "":
                    fromtext = str(head["RowID"])
                else:
                    fromtext = str(head["RowID"]) + "-" + str(head["ColumnID"])
            elif head["analysis"] == "sort":
                if "variableID1" in head.keys():
                    fromtext = str(head["variableID1"]) + "-" + str(head["variableID2"]) + "-" + str(
                        head["variableID3"])
                else:
                    fromtext = str(head["variableID"])
            else:
                fromtext = str(head["variableID"])
            if "outValue" in content.keys():
                fromtext += "-" + str(content["outValue"])
            text = noDescription
        else:
            if "outValue" in content.keys():
                if head["analysis"] == "wordcloud":
                    detailValid = datasource["detailValid"][0]
                    if len(detailValid) > 0:
                        if content["outValue"] == "count":
                            text = formatdata(float(str(detailValid[content["outValue"]])), 0)
                        elif content["outValue"] == "length":
                            text = str(len(detailValid))
                        else:
                            text = str(detailValid[content["outValue"]])
                else:
                    if content["outValue"] == "validP" or content["outValue"] == "invalidP" or \
                            content["outValue"] == "passRate" or content["outValue"] == "masteryRate":
                        text = head[content["outValue"]] * 100
                    elif content["outValue"] == "count":
                        if head["analysis"] == "means":
                            text = head[content["outValue"]]
                        else:
                            text, detailValid = 0, datasource["detailValid"]
                            for detailValidItem in detailValid:
                                text += int(detailValidItem["count"])
                    elif content["outValue"] == "variance_text" or content["outValue"] == "variance_F" or \
                            content["outValue"] == "variance_P" or content["outValue"] == "F_T_text" or \
                            content["outValue"] == "F_T_value" or content["outValue"] == "F_T_P" or \
                            content["outValue"] == "Chi_Square_text" or content["outValue"] == "Chi_Square_q" or \
                            content["outValue"] == "Chi_Square_P" or content["outValue"] == "pearson_text" or \
                            content["outValue"] == "pearson_r" or content["outValue"] == "pearson_p_value" or \
                            content["outValue"] == "spearman_text" or content["outValue"] == "spearman_r" or \
                            content["outValue"] == "spearman_p_value":
                        text = head[content["outValue"]]
                    elif content["outValue"] == "length":
                        detailValid = datasource["detailValid"]
                        text = str(len(detailValid))
                    else:
                        if content["outValue"] != "length":
                            text = head[content["outValue"]]
                if content["outValue"] == "validP" or content["outValue"] == "invalidP" or \
                    content["outValue"] == "average" or content["outValue"] == "median" or \
                    content["outValue"] == "stdev" or content["outValue"] == "variance" or \
                    content["outValue"] == "passRate" or content["outValue"] == "masteryRate" or \
                    content["outValue"] == "sum" or content["outValue"] == "max" or \
                    content["outValue"] == "min" or content["outValue"] == "mode" or \
                    content["outValue"] == "variance_F" or content["outValue"] == "variance_P" or \
                    content["outValue"] == "F_T_value" or content["outValue"] == "F_T_P" or \
                    content["outValue"] == "Chi_Square_q" or content["outValue"] == "Chi_Square_P" or \
                    content["outValue"] == "pearson_r" or content["outValue"] == "pearson_p_value" or \
                    content["outValue"] == "spearman_r" or content["outValue"] == "spearman_p_value":
                    text = str(formatdata(text, point))
                elif content["outValue"] == "count":
                    text = str(formatdata(text, 0))
                elif content["outValue"] == "length":
                    text = str(len(datasource["detailValid"]))
                else:
                    text = str(text)
                if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                        head["analysis"] == "comparemeans" or head["analysis"] == "crosstabsSort":
                    fromtext = str(head["RowID"]) + "-" + str(head["ColumnID"]) + "-" + str(content["outValue"])
                elif head["analysis"] == "sort":
                    if "variableID1" in head.keys():
                        fromtext = str(head["variableID1"]) + "-" + str(head["variableID2"]) + "-" \
                                   + str(head["variableID3"]) + "-" + content["outValue"]
                    else:
                        fromtext = str(head["variableID"]) + "-" + content["outValue"]
                else:
                    fromtext = str(head["variableID"]) + "-" + content["outValue"]
                text += units
                text = replacetext(text, replaceText)
            if head is not None and contentFlag:
                columnName = ['validpercent', 'casepercent', 'average', 'sum', 'count', 'passRate', 'masteryRate',
                              'percentileRank', 'variance_text', 'variance_F', 'variance_P', 'F_T_text', 'F_T_value',
                              'F_T_P', 'Chi_Square_text', 'Chi_Square_q', 'Chi_Square_P', 'pearson_text', 'pearson_r',
                              'pearson_p_value', 'spearman_text', 'spearman_r', 'spearman_p_value', 'textmax']
                formatKeyDict = {'validpercent': 'per', 'casepercent': 'caseper', 'average': 'avg',
                                 'textmax': 'namemax'}
                if "discription" in content["content"].keys():
                    text = content["content"]["discription"]
                else:
                    text = '{}'
                if str(head["analysis"]) == "crosstabs":
                    detailValid, detailValidFrom, valueColumn, exception = [], datasource["detailValid"], [], []
                    if "exception" in content["content"].keys():
                        if isinstance(content["content"]["exception"], list):
                            exception = content["content"]["exception"]
                        else:
                            exception.append(content["content"]["exception"])
                    for detailValidItem in detailValidFrom:
                        if detailValidItem["textColumn"] not in valueColumn and \
                                detailValidItem["textColumn"] not in exception:
                            valueColumn.append(detailValidItem["textColumn"])
                    for valueItem in valueColumn:
                        percent, count, textRow, valueRow = 0, 0, "", 0
                        for detailValidItem in detailValidFrom:
                            if valueItem == detailValidItem["textColumn"] and detailValidItem["validpercent"] > percent:
                                percent, count = detailValidItem["validpercent"], detailValidItem["count"]
                                textRow, valueRow = detailValidItem["textRow"], detailValidItem["valueRow"]
                        detailValid.append(dict(valueRow=valueRow, textRow=textRow, textColumn=valueItem,
                                                validpercent=percent, count=count))
                elif str(head["analysis"]) == "means":
                    detailValid = datasource["head"]
                else:
                    detailValid = datasource["detailValid"]
                if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                        head["analysis"] == "comparemeans" or head["analysis"] == "crosstabsSort":
                    if str(head["ColumnID"]).strip() == "":
                        fromtext = str(head["RowID"])
                    else:
                        fromtext = str(head["RowID"]) + "-" + str(head["ColumnID"])
                elif head["analysis"] == "sort":
                    if "variableID1" in head.keys():
                        fromtext = str(head["variableID1"]) + "-" + str(head["variableID2"]) + "-" + str(
                            head["variableID3"])
                    else:
                        fromtext = str(head["variableID"])
                else:
                    fromtext = str(head["variableID"])
                if "sort" in content["content"].keys():
                    sortValue, itemCount, reverse = "", "", False
                    if content["content"]["sort"] == "id" or content["content"]["sort"] == "-id":
                        if head["analysis"] == "crosstabs" or head["analysis"] == "comparemeans":
                            sortValue = "valueRow"
                        else:
                            sortValue = "value"
                    if content["content"]["sort"] == "text" or content["content"]["sort"] == "-text":
                        if head["analysis"] == "crosstabs" or head["analysis"] == "comparemeans":
                            sortValue = "textRow"
                        else:
                            sortValue = "text"
                    if str(content["content"]["sort"]).find(",") > -1:
                        sortWord = False
                        if isinstance(content["content"]["sort"], list):
                            sortKey = content["content"]["sort"]
                        else:
                            sortKey = str(content["content"]["sort"]).split(',')
                        if str(sortKey[0]).find("-") >= 0: sortWord = True
                        for sortKeyIndex, sortKeyItem in enumerate(sortKey):
                            sortKey[sortKeyIndex] = sortKeyItem.replace("-", "").replace("per", "validpercent"). \
                                replace("caseper", "casepercent").replace("avg", "average").replace("casevalid", "case")
                        if len(sortKey) == 2:
                            detailValid.sort(key=lambda x: (sort_key(x[str(sortKey[0])], sortWord),
                                                            sort_key(x[str(sortKey[1])], sortWord)), reverse=sortWord)
                        else:
                            detailValid.sort(key=lambda x: (sort_key(x[str(sortKey[0])], sortWord),
                                                            sort_key(x[str(sortKey[1])], sortWord),
                                                            sort_key(x[str(sortKey[2])], sortWord)), reverse=sortWord)
                    else:
                        if content["content"]["sort"].find('-') > -1: reverse = True
                        if content["content"]["sort"].find('caseper') > -1:
                            sortValue = 'casepercent'
                        elif content["content"]["sort"].find('pergroup') > -1:
                            detailValid = datasource["detailValidgroup"]
                            sortValue = 'validpercent'
                        elif content["content"]["sort"].find('per') > -1:
                            sortValue = 'validpercent'
                        elif content["content"]["sort"].find('avg') > -1:
                            sortValue = 'average'
                        elif content["content"]["sort"].find('textNum') > -1:
                            sortValue = 'textColumn'
                        else:
                            if sortValue == "":
                                sortValue = content["content"]["sort"].replace('-', '')
                            else:
                                if sortValue in detailValid[0].keys():
                                    detailValid.sort(key=lambda x: x[sortValue], reverse=reverse)
                                sortValue = ''
                        if sortValue != '' and sortValue in detailValid[0].keys():
                            detailValid.sort(key=lambda x: sort_key(x[sortValue], reverse), reverse=reverse)
                    if "textColumn" in detailValid[0].keys(): outColumn = "textColumn"
                    if "count" in detailValid[0].keys(): outColumn = "count"
                    if "validpercent" in detailValid[0].keys(): outColumn = "validpercent"
                    if "casepercent" in detailValid[0].keys(): outColumn = "casepercent"
                    if "average" in detailValid[0].keys(): outColumn = "average"
                    if "outColumn" in content["content"].keys():
                        outColumn = content["content"]["outColumn"]
                    else:
                        if sortValue != '' and sortValue in detailValid[0].keys():
                            if str(content["content"]["sort"]).find("count") >= 0:
                                outColumn = "count"
                            elif str(content["content"]["sort"]).find("avg") >= 0:
                                outColumn = "average"
                            elif str(content["content"]["sort"]).find("per") >= 0:
                                if str(content["content"]["sort"]).find("caseper") >= 0:
                                    outColumn = "casepercent"
                                else:
                                    outColumn = "validpercent"
                            elif str(content["content"]["sort"]).find("textNum") >= 0:
                                outColumn = "textColumn"
                    if isinstance(outColumn, list) and "value" in detailValid[0].keys():
                        outColumn = "value"
                    if "exception" in content["content"].keys():
                        deletenum = []
                        for num in range(0, len(detailValid)):
                            if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                                    head["analysis"] == "comparemeans" or head["analysis"] == "crosstabsSort":
                                optionname = detailValid[num]["textRow"]
                            else:
                                if "optiontext" in detailValid[num].keys():
                                    optionname = detailValid[num]["optiontext"]
                                else:
                                    optionname = detailValid[num]["text"]
                            if isinstance(content["content"]["exception"], list):
                                for exceptionItem in content["content"]["exception"]:
                                    if str(optionname).strip() == str(exceptionItem).strip():
                                        deletenum.append(num)
                                        break
                            else:
                                if str(optionname).strip() == str(content["content"]["exception"]).strip():
                                    deletenum.append(num)
                        if len(deletenum) > 0:
                            for deletenumItem in reversed(deletenum):
                                del detailValid[deletenumItem]
                    top, topValue, totalPer, totalNum, firstFlag, textRow, textColumn, topReplace, topReplaceIndex, \
                    columnReplace, columnReplaceTo = len(detailValid), 0, 0.0, 0, False, "", "", -1, 0, [], []
                    contentFirstFlag, contentLastFlag = False, False
                    contentFirst = textEqualReturn(outColumn, detailValid, point, 0)
                    contentLast = textEqualReturn(outColumn, detailValid, point, len(detailValid) - 1)
                    if contentFirst == contentLast == len(detailValid): contentLast = 0
                    if isinstance(replaceText, list):
                        for replaceIndex, replaceItem in enumerate(replaceText[0]):
                            if isinstance(replaceItem, dict):
                                if "top" in replaceItem.keys():
                                    topReplace, topReplaceIndex = replaceItem["top"], replaceIndex
                                    if str(topReplace).strip().find("%") < 0:
                                        if len(content["content"]["top"]) > 1:
                                            if str(content["content"]["top"][1]).strip() == "False":
                                                topReplace = returncountRepeat(detailValid, int(topReplace), outColumn,
                                                                               point)
                                            else:
                                                if int(topReplace) > len(detailValid): topReplace = len(detailValid)
                                        else:
                                            topReplace = returncount(detailValid, int(topReplace), outColumn, point)
                                else:
                                    for columnIndex in range(20):
                                        if "column" + str(columnIndex) in replaceItem.keys():
                                            if str(detailValid[0]['columnName0']).strip() == '固定值':
                                                columnNameIndex = columnIndex + 1
                                            else:
                                                columnNameIndex = columnIndex
                                            columnReplaceKey = str(detailValid[0]['columnName' + str(columnNameIndex)]). \
                                                replace('固定值', '')
                                            if columnIndex > 0: columnReplaceKey += str(columnIndex)
                                            columnReplace.append(
                                                [columnReplaceKey, replaceItem["column" + str(columnIndex)]])
                                            columnReplaceTo.append(replaceText[1][replaceIndex])
                                            break
                    if "top" in content["content"].keys() and top > 0:
                        if isinstance(content["content"]["top"], list):
                            if content["content"]["top"][0] != '':
                                top = int(content["content"]["top"][0])
                            if len(content["content"]["top"]) > 1:
                                if str(content["content"]["top"][1]).strip() == "False":
                                    top = returncountRepeat(detailValid, int(top), outColumn, point)
                                else:
                                    if int(top) > len(detailValid): top = len(detailValid)
                            else:
                                topValue = top
                                if not (isinstance(content["content"]["text"], str) and
                                        str(content["content"]["text"]).find("name") < 0 and top == 1):
                                    top = returncount(detailValid, int(top), outColumn, point)
                        else:
                            if str(content["content"]["top"]).strip().find("%") > -1 and \
                                    (outColumn == "casepercent" or outColumn == "validpercent" or
                                     outColumn == "average"):
                                top, maxValue, maxValueReplace = \
                                    0, float(str(content["content"]["top"]).strip().replace("%", "")), 0
                                if str(topReplace).strip().find("%") > -1:
                                    maxValueReplace = float(str(topReplace).strip().replace("%", ""))
                                    topReplace = 0
                                for detailValidItem in detailValid:
                                    if outColumn == "casepercent" or outColumn == "validpercent":
                                        detailValidItemValue = float(str(formatdata(detailValidItem[outColumn] * 100,
                                                                                    point)))
                                    else:
                                        detailValidItemValue = float(str(formatdata(detailValidItem[outColumn], point)))
                                    if detailValidItemValue >= maxValue:
                                        top += 1
                                    if topReplace != -1 and detailValidItemValue >= maxValueReplace:
                                        topReplace += 1
                            else:
                                top = int(content["content"]["top"])
                                if outColumn == 'validpercent' or outColumn == 'casepercent' or outColumn == 'average' \
                                        or outColumn == 'count':
                                    head, detailValid, itemCount, top = \
                                        detailValidOrderReset(head, detailValid, wordHead, outColumn,
                                                              content["content"]["sort"], top, point)
                                topValue = top
                                if not (isinstance(content["content"]["text"], str) and
                                        str(content["content"]["text"]).find("name") < 0 and top == 1):
                                    top = returncount(detailValid, int(top), outColumn, point)
                        if len(detailValid) == 0: top = 0
                    if "topStar" in content["content"].keys(): topStar = int(float(content["content"]["topStar"]))
                    num_dict, equalList, value2 = ['零', '一', '两', '三', '四', '五', '六', '七', '八', '九'], [], 0
                    if topStar < top and len(detailValid) > 0:
                        for topNum in range(topStar, top):
                            if outColumn == "validpercent" or outColumn == "casepercent":
                                value0 = float(str(formatdata(sort_key(detailValid[0][outColumn], None) * 100, point)))
                                value1 = float(
                                    str(formatdata(sort_key(detailValid[topNum][outColumn], None) * 100, point)))
                                if topNum > 0:
                                    value2 = float(
                                        str(formatdata(sort_key(detailValid[topNum - 1][outColumn], None) * 100,
                                                       point)))
                            else:
                                value0 = float(str(formatdata(sort_key(detailValid[0][outColumn], None), point)))
                                value1 = float(str(formatdata(sort_key(detailValid[topNum][outColumn], None), point)))
                                if topNum > 0:
                                    value2 = float(
                                        str(formatdata(sort_key(detailValid[topNum - 1][outColumn], None), point)))
                            if topNum > 0:
                                if value0 != value1: equalFlag = False
                                if value1 == value2:
                                    equalList.append("=")
                                else:
                                    equalList.append("")
                            else:
                                if top == 1: equalFlag = False
                                equalList.append("")
                            if (outColumn == "validpercent" or outColumn == "casepercent") and \
                                    detailValid[topNum][outColumn] is not None:
                                totalPer += sort_key(detailValid[topNum][outColumn], None)
                            if "count" in detailValid[topNum].keys() and detailValid[topNum]["count"] is not None:
                                totalNum += sort_key(detailValid[topNum]["count"], None)
                    discriptionwordargs["totalPer"] = formatdata(totalPer * 100, point) + units
                    discriptionwordargs["totalNum"] = formatdata(totalNum, 0)
                    if len(detailValid) > 0 and isinstance(outColumn, str):
                        if 'validpercent' in detailValid[0].keys():
                            discriptionwordargs["per"] = \
                                formatdata(sort_key(detailValid[0]['validpercent'], None) * 100, point) + units
                        if 'average' in detailValid[0].keys():
                            discriptionwordargs["avg"] = \
                                formatdata(sort_key(detailValid[0]['average'], None), point)
                        if 'text' in detailValid[0].keys(): discriptionwordargs["name"] = str(detailValid[0]['text'])
                        if 'textRow' in detailValid[0].keys(): discriptionwordargs["name"] = str(
                            detailValid[0]['textRow'])
                    if top > 0 and topStar < top:
                        if topStar > 0 and topStar + 5 < top: top = topStar + 5
                        numFrom, numTo, numStep = topStar, top, 1
                        if bigToSmall != '':
                            numFrom = top - 1
                            numTo = topStar - 1
                            numStep = -1
                        for num in range(numFrom, numTo, numStep):
                            if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                                    head["analysis"] == "crosstabsSort":
                                if isinstance(detailValid[num]["textColumn"], list):
                                    optionname = ""
                                    for textItem in detailValid[num]["textColumn"]:
                                        optionname += str(textItem).strip()
                                else:
                                    optionname = detailValid[num]["textColumn"]
                                if isinstance(detailValid[num]["textRow"], list):
                                    textRow = ""
                                    for textItem in detailValid[num]["textRow"]:
                                        textRow += str(textItem).strip()
                                else:
                                    textRow = detailValid[num]["textRow"]
                                optionId = str(detailValid[num]["valueRow"])
                            elif head["analysis"] == "comparemeans":
                                if isinstance(detailValid[num]["textRow"], list):
                                    optionname = ""
                                    for textItem in detailValid[num]["textRow"]:
                                        optionname += str(textItem).strip()
                                else:
                                    optionname = detailValid[num]["textRow"]
                                optionId = str(detailValid[num]["valueRow"])
                            else:
                                if "text" in detailValid[num].keys():
                                    if "optiontext" in detailValid[num].keys():
                                        optionname = detailValid[num]["optiontext"]
                                    else:
                                        if isinstance(detailValid[num]["text"], list):
                                            optionname = ""
                                            for textItem in detailValid[num]["text"]:
                                                optionname += str(textItem).strip()
                                        else:
                                            optionname = detailValid[num]["text"]
                                else:
                                    optionname = ''
                                if "value" in detailValid[num].keys():
                                    optionId = str(detailValid[num]["value"])
                                else:
                                    optionId = ''
                            columnValue = {'validpercent': [""], 'casepercent': [""], 'average': [""], 'passRate': "",
                                           'masteryRate': "", 'percentileRank': "", 'count': [0], 'sum': [""],
                                           'variance_text': "", 'variance_F': "", 'variance_P': "", 'F_T_text': "",
                                           'F_T_value': "", 'F_T_P': "", 'Chi_Square_text': "", 'Chi_Square_q': "",
                                           'Chi_Square_P': "", 'pearson_text': "", 'pearson_r': "",
                                           'pearson_p_value': "", 'spearman_text': "", 'spearman_r': "",
                                           'spearman_p_value': "", 'textmax': ""}
                            outColumnFlag, outColumnList, columnComplete = False, False, []
                            for columnIndex in range(20):
                                columnIndexStr, columnIndexFlag = '', False
                                if columnIndex > 0: columnIndexStr = str(columnIndex)
                                for columnItem in columnName:
                                    if columnItem in head.keys():
                                        columnIndexFlag = True
                                        if columnItem == 'variance_F' or columnItem == 'variance_P' or \
                                                columnItem == 'F_T_value' or columnItem == 'F_T_P' or \
                                                columnItem == 'Chi_Square_q' or columnItem == 'Chi_Square_P' or \
                                                columnItem == 'pearson_r' or columnItem == 'pearson_p_value' or \
                                                columnItem == 'spearman_r':
                                            columnValue[columnItem] = \
                                                str(formatdata(sort_key(head[columnItem], None), point))
                                        elif columnItem == 'variance_text' or columnItem == 'F_T_text' or \
                                                columnItem == 'Chi_Square_text' or columnItem == 'pearson_text' or \
                                                columnItem == 'spearman_text' or columnItem == 'textmax':
                                            columnValue[columnItem] = str(head[columnItem])
                                    if columnItem + columnIndexStr in detailValid[0].keys():
                                        columnIndexFlag = True
                                        if isinstance(detailValid[num][columnItem + columnIndexStr], list):
                                            outColumnList = True
                                            columnValueItem, outColumnFlag = outListValueFormat(columnItem,
                                                                                                detailValid[num][
                                                                                                    columnItem + columnIndexStr],
                                                                                                point)
                                        else:
                                            if columnItem == 'validpercent' or columnItem == 'casepercent' or \
                                                    columnItem == 'passRate' or columnItem == 'masteryRate' or \
                                                    columnItem == 'percentileRank':
                                                columnValueItem = str(formatdata(sort_key(detailValid[num][columnItem +
                                                                                                           columnIndexStr],
                                                                                          None) * 100, point)) + units
                                            elif columnItem == 'count':
                                                columnValueItem = int(
                                                    str(detailValid[num][columnItem + columnIndexStr]).
                                                    split('.')[0])
                                            elif columnItem == 'variance_text' or columnItem == 'F_T_text' or \
                                                    columnItem == 'Chi_Square_text' or columnItem == 'pearson_text' or \
                                                    columnItem == 'spearman_text' or columnItem == 'textmax':
                                                columnValueItem = str(detailValid[num][columnItem + columnIndexStr])
                                            else:
                                                columnValueItem = str(formatdata(
                                                    sort_key(detailValid[num][columnItem + columnIndexStr], None),
                                                    point))
                                        if columnItem == 'validpercent' or columnItem == 'casepercent' or \
                                                columnItem == 'average' or columnItem == 'sum' or columnItem == 'count':
                                            if columnIndex == 0:
                                                columnValue[columnItem][0] = columnValueItem
                                            else:
                                                columnValue[columnItem].append(columnValueItem)
                                        else:
                                            columnValue[columnItem] = columnValueItem
                                if not columnIndexFlag: break
                            for columnReplaceIndex, columnReplaceItem in enumerate(columnReplace):
                                columnReplaceKey = columnReplaceItem[0]
                                columnReplaceValue = columnReplaceItem[1]
                                if columnReplaceKey in columnComplete: continue
                                columnIndexStr = "".join(list(filter(str.isdigit, str(columnReplaceKey).strip())))
                                columnIndex, replaceDoneFlag = 0, False
                                if columnIndexStr != '': columnIndex = int(columnIndexStr)
                                columnIndexStrReplace = str(columnReplaceKey).replace(columnIndexStr, '')
                                compareStr = ['>=', '<=', '>', '<', '=']
                                for compareStrItem in compareStr:
                                    if str(columnReplaceValue).strip().find(compareStrItem) >= 0:
                                        replaceDoneFlag = True
                                        if str(columnReplaceValue).strip().find(compareStrItem) == 0:
                                            compareValueTo = float(str(columnReplaceValue).replace(compareStrItem, ''))
                                        else:
                                            compareValueTo = str(columnReplaceValue).split(compareStrItem)
                                        if columnIndexStrReplace == 'validpercent' or \
                                                columnIndexStrReplace == 'casepercent' or \
                                                columnIndexStrReplace == 'average' or \
                                                columnIndexStrReplace == 'sum' or columnIndexStrReplace == 'count':
                                            if compareValueReturn(compareStrItem,
                                                                  float(
                                                                      columnValue[columnIndexStrReplace][columnIndex]),
                                                                  compareValueTo):
                                                columnComplete.append(columnReplaceKey)
                                                columnValue[columnIndexStrReplace][columnIndex] = \
                                                    columnReplaceTo[columnReplaceIndex]
                                        break
                                if not replaceDoneFlag:
                                    columnValue[columnIndexStrReplace][columnIndex] = \
                                        columnValue[columnIndexStrReplace][columnIndex]. \
                                            replace(columnReplaceValue, columnReplaceTo[columnReplaceIndex])
                            discriptionwordDict = dict(name=optionname, nameRow=textRow, nameColumn=textColumn)
                            for columnValueKey, columnValueItem in columnValue.items():
                                if columnValueKey == 'validpercent' or columnValueKey == 'casepercent' or \
                                        columnValueKey == 'average' or columnValueKey == 'sum' or columnValueKey == 'count':
                                    formatValue, formatKey = [], columnValueKey
                                    formatValue = copy.deepcopy(columnValueItem)
                                    if columnValueKey in formatKeyDict.keys():
                                        formatKey = formatKeyDict[columnValueKey]
                                    for columnIndex in range(len(formatValue)):
                                        columnIndexStr = ''
                                        if columnIndex > 0: columnIndexStr = str(columnIndex)
                                        discriptionwordDict[formatKey + columnIndexStr] = formatValue[columnIndex]
                                elif columnValueKey == 'textmax':
                                    formatKey = columnValueKey
                                    if columnValueKey in formatKeyDict.keys():
                                        formatKey = formatKeyDict[columnValueKey]
                                    discriptionwordDict[formatKey] = columnValueItem
                                else:
                                    discriptionwordDict[columnValueKey] = columnValueItem
                            if "textColumn" in detailValid[0].keys():
                                textColumn = str(detailValid[num]["textColumn"])
                            if optionId in content["content"].keys():
                                discriptionword.append(content["content"][optionId]. \
                                                       format(**discriptionwordDict).format(**discriptionwordDict))
                            elif "textall" in content["content"].keys():
                                valueIndex = "value"
                                if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                                        head["analysis"] == "comparemeans" or head["analysis"] == "crosstabsSort":
                                    valueIndex = "valueRow"
                                for itemIndex, itemText in enumerate(content["content"]["textall"]):
                                    textFlag = False
                                    if "text" in content["content"].keys() and \
                                            isinstance(content["content"]["text"], list):
                                        if str(content["content"]["text"][itemIndex]).strip() == \
                                                str(detailValid[num][valueIndex]).strip():
                                            textFlag = True
                                    else:
                                        if float(itemIndex + 1) == float(detailValid[num][valueIndex]):
                                            textFlag = True
                                    if textFlag:
                                        if "text2" in content["content"].keys() and firstFlag == False:
                                            discriptionword.append(content["content"]["text2"].
                                                                   format(**discriptionwordDict).
                                                                   format(**discriptionwordDict))
                                            firstFlag = True
                                        else:
                                            discriptionword.append(itemText.format(**discriptionwordDict).
                                                                   format(**discriptionwordDict))
                            else:
                                if not outColumnList and len(discriptionword) < contentFirst: outColumnFlag = True
                                if "text2" in content["content"].keys() and outColumnFlag:
                                    contentText, contentFirstFlag = content["content"]["text2"], True
                                elif "text3" in content["content"].keys() and len(discriptionword) == \
                                        (top - topStar - contentLast) and top - topStar > 2 and not equalFlag:
                                    contentText, contentLastFlag = content["content"]["text3"], True
                                else:
                                    if isinstance(content["content"]["text"], list) and len(
                                            content["content"]["text"]) > 0:
                                        if not equalFlag or len(content["content"]["text"]) == 1:
                                            contentText = content["content"]["text"][0]
                                        else:
                                            contentText = content["content"]["text"][1]
                                    else:
                                        contentText = content["content"]["text"]
                                if top > topValue > 0 and equalFlag and num > 0 and isinstance(text, list):
                                    break
                                discriptionword.append(contentText. \
                                                       format(**discriptionwordDict).format(**discriptionwordDict))
                    discriptionwordargs["textColumn"] = textColumn
                    if isinstance(connector, str) or isinstance(connector, list):
                        if isinstance(connector, str):
                            connector = [connector]
                        if isinstance(connector, list) and len(connector) == 1: connector.append(connector[0])
                        discriptionwordNew,discriptionwordFirstNew, discriptionwordLastNew = "", "", ""
                        for discriptionItem in discriptionword:
                            if discriptionItem.find('、') > -1:
                                if not (discriptionItem.find('（') < discriptionItem.find('、') < discriptionItem.find(
                                        '）')):
                                    if isinstance(connector, list):
                                        for connectorIndex in range(len(connector)):
                                            connector[connectorIndex] = connector[connectorIndex].replace("、", "，")
                                    break
                        for discriptionIndex, discriptionItem in enumerate(discriptionword):
                            if isinstance(connector, str):
                                connectorText = connector
                            else:
                                if discriptionIndex == len(discriptionword) - 1:
                                    connectorText = connector[1]
                                else:
                                    connectorText = connector[0]
                            if (connectorText == '>' or connectorText == '<') and discriptionIndex < len(equalList) and \
                                    equalList[discriptionIndex] == '=':
                                connectorText = '='
                            if (discriptionwordNew != "" or discriptionwordFirstNew != "" or
                                discriptionwordLastNew != "") and discriptionItem != "":
                                if discriptionwordFirstNew != "" and discriptionIndex < contentFirst:
                                    discriptionwordFirstNew += connectorText
                                if discriptionwordNew != "" and (not contentLastFlag or
                                                                 discriptionIndex < top - topStar - contentLast):
                                    discriptionwordNew += connectorText
                                if discriptionwordLastNew != "" and discriptionwordLastNew[-1:] != connectorText:
                                    discriptionwordLastNew += connectorText
                            if discriptionIndex < topReplace + 1:
                                replaceText[0][topReplaceIndex] = discriptionwordNew
                            if not contentFirstFlag and topReplace == -1: contentFirst = 0
                            if contentFirstFlag and discriptionIndex < contentFirst:
                                discriptionwordFirstNew += discriptionItem
                            elif contentLastFlag and discriptionIndex >= top - topStar - contentLast and \
                                    top - contentFirst != contentLast:
                                discriptionwordLastNew += discriptionItem
                            else:
                                discriptionwordNew += discriptionItem
                        if topReplace != -1 and topReplace >= len(discriptionword):
                            replaceText[0][topReplaceIndex] = discriptionwordNew
                        discriptionword = [discriptionwordNew]
                        if discriptionwordFirstNew != '': discriptionwordargs["first"] = discriptionwordFirstNew
                        if discriptionwordLastNew != '': discriptionwordargs["last"] = discriptionwordLastNew
                    if isinstance(text, list) and len(text) > 0:
                        if equalFlag and len(text) >= 2:
                            if top > topValue and len(text) >= 3:
                                text = text[2]
                                if text.find('【全部清空】') > 0:
                                    if top == len(detailValid):
                                        text = ''
                                    else:
                                        text = text.replace('【全部清空】', '')
                                if text.find('【全部不清空】') > 0:
                                    if top == len(detailValid):
                                        text = text.replace('【全部不清空】', '')
                                    else:
                                        text = ''
                            else:
                                text = text[1]
                        elif equalFlag and len(text) == 2:
                            text = text[1]
                        elif top == 1 and len(text) == 4:
                            text = text[3]
                        else:
                            text = text[0]
                    if text.find('{last}') > -1 and 'last' not in discriptionwordargs.keys():
                        discriptionwordargs["last"] = ''
                    if text.find('{first}') > -1 and 'first' not in discriptionwordargs.keys():
                        discriptionwordargs["first"] = ''
                    topLow = len(detailValid) - top
                    if text.find('{last}') == -1 and 'last' in discriptionwordargs.keys(): topLow += contentLast
                    if text.find('{}') == -1: topLow += len(discriptionword)
                    if text.find('{low}') > -1:
                        if topLow <= 0:
                            discriptionwordargs["low"] = ''
                        else:
                            discriptionwordargs["low"] = \
                                discriptionwordLowReturn(content, head, detailValid, outColumn, point, connector)
                    if 0 < topStar < top:
                        discriptionwordargs["top"] = str(top - topStar)
                    else:
                        if top < 4:
                            discriptionwordargs["top"] = num_dict[top]
                        else:
                            discriptionwordargs["top"] = str(top)
                    if 1 < text.count('{}') < top: top = text.count('{}')
                    textNone = None
                    if text.count('{}') == 1: textNone = text.replace('{}', '')
                    if len(discriptionword) < 20:
                        for discriptionIndex in range(20 - len(discriptionword)):
                            discriptionword.append("")
                    if topStar < top:
                        if topReplace != -1 and discriptionword[1] != '':
                            for topReplaceIndex in range(topReplace):
                                del discriptionword[topReplaceIndex]
                        if len(discriptionwordargs) > 0:
                            text = text.format(*discriptionword, **discriptionwordargs)
                        else:
                            text = text.format(*discriptionword)
                        if topStar > 0 and topStar + 1 == top:
                            text = ""
                    else:
                        text = ""
                    if "phrase" in content["content"].keys():
                        phrase = content["content"]["phrase"]
                        outValue = str(phrase).split(':')
                        datasourceOut = json.loads(json_data[outValue[0]])
                        outValueText = str(datasourceOut["detailValid"][0][outValue[1]]).strip()
                        for detailValidIndex, detailValidItem in enumerate(detailValid):
                            if 'textRow' in detailValidItem.keys():
                                detailValidItemText = str(detailValidItem["textRow"]).strip()
                                detailValidItemValue = str(detailValidItem["valueRow"]).strip()
                            else:
                                detailValidItemText = str(detailValidItem["text"]).strip()
                                detailValidItemValue = str(detailValidItem["value"]).strip()
                            if outValueText == detailValidItemText or outValueText == \
                                    detailValidItemValue + detailValidItemText:
                                detailValidIndexText = copy.deepcopy(detailValidIndex)
                                if detailValidIndex > 0:
                                    for detailValidIndexDrop in range(detailValidIndex - 1, -1, -1):
                                        if detailValid[detailValidIndexDrop][outColumn] == detailValidItem[outColumn]:
                                            detailValidIndexText -= 1
                                        else:
                                            break
                                text = str(detailValidIndexText + 1)
                                break
                    text = replacetext(text, replaceText)
                    if top == 0 and text != "":
                        text = text[-1]
                    if text == '' or (textNone is not None and textNone == text): text = noDescription
                    elif ai_polishing.strip() != "":
                        contentStr = text + '\n' + ai_polishing
                        text = deepSeekai_description(contentStr)
                elif "compare" in content["content"].keys():
                    if "sortArray" in content["content"].keys():
                        if rowText != "":
                            sortKey = 0
                        else:
                            sortKey = 1
                        detailValid.sort(key=lambda x: x["column" + str(sortKey)], reverse=False)
                        sortArray = content["content"]["sortArray"]
                        compare, arrayText = content["content"]["compare"], ""
                        for sortIndex, sortItem in enumerate(sortArray):
                            equalFlag = False
                            for arrayIndex, arrayItem in sortItem:
                                if str(arrayItem).strip() != "" and arrayIndex < len(detailValid) and \
                                        str(arrayItem).strip() == str(detailValid[arrayIndex]["value"]).strip():
                                    equalFlag = True
                            if equalFlag and sortIndex < len(compare):
                                arrayText = compare[sortIndex]
                        percent, value, num, option, percentCompare, valueCompare, numCompare, equalFlag = \
                            [], [], [], [], 0, 0, 0, False
                        percentFrom, valueFrom, numFrom, percentTo, valueTo, numTo = "", "", "", "", "", ""
                        for detailValidIndex, detailValidItem in enumerate(detailValid):
                            percent.append(formatdata(float(detailValidItem[sortKey]) * 100, point))
                            value.append(formatdata(float(detailValidItem[sortKey]), point))
                            num.append(formatdata(float(detailValidItem[sortKey]), 0))
                            option.append(str(detailValidItem["text"]).strip())
                            if detailValidIndex == 0:
                                percentCompare = float(detailValidItem[sortKey]) * 100
                                valueCompare = float(detailValidItem[sortKey])
                                numCompare = float(detailValidItem[sortKey])
                            if detailValidIndex == len(detailValid) - 1:
                                percentCompare = formatdata(float(detailValidItem[sortKey]) * 100 - percentCompare,
                                                            point)
                                valueCompare = formatdata(float(detailValidItem[sortKey]) - valueCompare, point)
                                numCompare = formatdata(float(detailValidItem[sortKey]) - numCompare, 0)
                        if len(percent) > 0 and len(value) > 0 and len(num) > 0:
                            percentFrom, valueFrom, numFrom = percent[0], value[0], num[0]
                            percentTo, valueTo, numTo = percent[len(percent) - 1], value[len(value) - 1], num[
                                len(num) - 1]
                        if len(compare) > len(sortArray):
                            if percentCompare < 2.0 or valueCompare < 1.0:
                                arrayText = compare[len(sortArray)]
                        if len(compare) > len(sortArray) + 1:
                            if float(str(formatdata(percentCompare, point))) == 0.0 or \
                                    float(str(formatdata(valueCompare, point))) == 0.0:
                                arrayText = compare[len(sortArray) + 1]
                        discriptionword.append(content["content"]["text"].
                                               format(text=arrayText, percentCompare=percentCompare,
                                                      valueCompare=valueCompare, numCompare=numCompare, percent=percent,
                                                      value=value, count=num, option=option, percentFrom=percentFrom,
                                                      valueFrom=valueFrom, numFrom=numFrom, percentTo=percentTo,
                                                      valueTo=valueTo, numTo=numTo))
                    elif "group" in content.keys() or "group" in content["content"].keys():
                        if "group" in content.keys():
                            compareGroup = content["group"]
                        else:
                            compareGroup = content["content"]["group"]
                        if "text2" in content["content"].keys() and \
                                str(content["content"]["text2"]).strip() != "":
                            if "count" in detailValid[0].keys(): outColumn = "count"
                            if "validpercent" in detailValid[0].keys(): outColumn = "validpercent"
                            if "casepercent" in detailValid[0].keys(): outColumn = "casepercent"
                            if "average" in detailValid[0].keys(): outColumn = "average"
                            if "sum" in detailValid[0].keys(): outColumn = "sum"
                            detailValid.sort(key=lambda x: x[outColumn], reverse=True)
                        for groupIndex, groupItem in enumerate(compareGroup[0]):
                            detailText, nameStr, connectorText, count, validpercent, average, casepercent, sum = \
                                [], "", "", [], [], [], [], []
                            for dataItem in detailValid:
                                compareFlag, headFlag = compareReturn(compareGroup[1][groupIndex], groupItem,
                                                                      compareGroup[2][groupIndex], dataItem, head)
                                if compareFlag:
                                    if "text" in dataItem.keys():
                                        detailText.append(str(dataItem["text"]).strip())
                                    elif "textRow" in dataItem.keys():
                                        detailText.append(str(dataItem["textRow"]).strip())
                                    else:
                                        detailText.append('')
                                    if "count" in dataItem.keys() and dataItem["count"] is not None:
                                        count.append(str(formatdata(dataItem["count"], 0)))
                                    else:
                                        count.append('')
                                    if "sum" in dataItem.keys() and dataItem["sum"] is not None:
                                        sum.append(str(formatdata(dataItem["sum"], 0)))
                                    else:
                                        sum.append('')
                                    if "validpercent" in dataItem.keys() and dataItem["validpercent"] is not None:
                                        validpercent.append(str(formatdata(dataItem["validpercent"] * 100, point)))
                                    else:
                                        validpercent.append('')
                                    if "casepercent" in dataItem.keys() and dataItem["casepercent"] is not None:
                                        casepercent.append(str(formatdata(dataItem["casepercent"] * 100, point)))
                                    else:
                                        casepercent.append('')
                                    if "average" in dataItem.keys() and dataItem["average"] is not None:
                                        average.append(str(formatdata(dataItem["average"], point)))
                                    else:
                                        average.append('')
                                if headFlag: break
                            if len(detailText) > 0:
                                for textIndex, textItem in enumerate(detailText):
                                    if nameStr != "":
                                        if connector is not None:
                                            if isinstance(connector, str):
                                                nameStr += connector
                                            else:
                                                if isinstance(connector, list) and len(connector) == 1:
                                                    connector.append(connector[0])
                                                if textIndex == len(detailText) - 1:
                                                    nameStr += connector[1]
                                                else:
                                                    nameStr += connector[0]
                                    nameStr += textItem
                                if isinstance(content["content"]["compare"], list):
                                    if groupIndex < len(content["content"]["compare"]):
                                        connectorText = content["content"]["compare"][groupIndex]
                                    else:
                                        connectorText = content["content"]["compare"][0]
                                if isinstance(content["content"]["compare"], str):
                                    connectorText = str(content["content"]["compare"])
                                discriptionTextCompare, discriptionTextCompare2, discriptionText, discriptionText2 = \
                                    "", "", "", ""
                                discriptionWordString = ""
                                if isinstance(content["content"]["text"], str):
                                    if str(content["content"]["text"]).find('compare') > -1:
                                        discriptionTextCompare = str(content["content"]["text"])
                                    else:
                                        discriptionText = str(content["content"]["text"])
                                    if "text2" in content["content"].keys() and \
                                            str(content["content"]["text2"]).strip() != "":
                                        if str(content["content"]["text2"]).find('compare') > -1:
                                            discriptionTextCompare2 = str(content["content"]["text2"])
                                        else:
                                            discriptionText2 = str(content["content"]["text2"])
                                    if (discriptionText != "" and discriptionText2 != "") or \
                                            (discriptionTextCompare != "" and discriptionTextCompare2 != ""):
                                        if len(discriptionword) == 0:
                                            discriptionText, discriptionTextCompare = '', ''
                                        else:
                                            discriptionText2, discriptionTextCompare2 = '', ''
                                    if discriptionText != "" or discriptionText2 != "":
                                        for detailTextIndex, detailTextItem in enumerate(detailText):
                                            discriptionWordString = discriptionWordString + \
                                                                    (discriptionText + discriptionText2). \
                                                                        format(name=detailTextItem,
                                                                               per=validpercent[detailTextIndex],
                                                                               caseper=casepercent[detailTextIndex],
                                                                               avg=average[detailTextIndex],
                                                                               sum=sum[detailTextIndex],
                                                                               compare=connectorText)
                                    if discriptionTextCompare != "" or discriptionTextCompare2 != "":
                                        discriptionword.append(discriptionWordString + \
                                                               (discriptionTextCompare + discriptionTextCompare2).
                                                               format(name=nameStr, compare=connectorText,
                                                                      per=validpercent[0], caseper=casepercent[0],
                                                                      avg=average[0], sum=sum[0]))
                                discriptionwordDict = dict(name=nameStr, compare=connectorText, per=validpercent[0],
                                                           caseper=casepercent[0], avg=average[0], sum=sum[0])
                                if isinstance(content["content"]["text"], list):
                                    if groupIndex < len(content["content"]["text"]):
                                        discriptionword.append(content["content"]["text"][groupIndex].
                                                               format(**discriptionwordDict))
                                    else:
                                        discriptionword.append(content["content"]["text"][0].
                                                               format(**discriptionwordDict))
                                else:
                                    if len(discriptionword) == 0 and nameStr != '':
                                        discriptionword.append(content["content"]["text"].
                                                               format(**discriptionwordDict))
                    else:
                        if head["analysis"] == "crosstabs":
                            if len(datasource["detailValidgroup"]) > 0:
                                detailValid = datasource["detailValidgroup"]
                            else:
                                detailValid = datasource["detailValid"]
                        compare = content["content"]["compare"]
                        value1, count1, option1, value2, count2, option2 = 0, 0, "", 0, 0, ""
                        if head["analysis"] == "frequency" or head["analysis"] == "multiple":
                            if isinstance(compare[0], list):
                                value1, count1, option1, value2, count2, option2 = [], [], [], [], [], []
                                for groupInd, compareGroup in enumerate(compare):
                                    for dataItem in detailValid:
                                        if str(compareGroup[0]).strip() == str(dataItem["value"]).strip() or \
                                                str(compareGroup[0]).strip() == str(dataItem["text"]).strip():
                                            if "validpercent" in dataItem.keys():
                                                value1.append(formatdata(float(dataItem["validpercent"]) * 100, point))
                                            if "casepercent" in dataItem.keys():
                                                value1.append(formatdata(float(dataItem["casepercent"]) * 100, point))
                                            if "average" in dataItem.keys():
                                                value1.append(formatdata(float(dataItem["average"]), point))
                                            if "textmax" in dataItem.keys():
                                                value1.append(float(sort_key(str(dataItem["textmax"]), None)))
                                            if "count" in dataItem.keys():
                                                count1.append(int(dataItem["count"]))
                                            else:
                                                if "column1" in dataItem.keys():
                                                    count1.append(int(sort_key(dataItem["column1"], None)))
                                            option1.append(dataItem["text"])
                                        elif str(compareGroup[1]).strip() == str(dataItem["value"]).strip() or \
                                                str(compareGroup[1]).strip() == str(dataItem["text"]).strip():
                                            if "validpercent" in dataItem.keys():
                                                value2.append(formatdata(float(dataItem["validpercent"]) * 100, point))
                                            if "average" in dataItem.keys():
                                                value2.append(formatdata(float(dataItem["average"]), point))
                                            if "textmax" in dataItem.keys():
                                                value2.append(float(sort_key(str(dataItem["textmax"]), None)))
                                            if "casepercent" in dataItem.keys():
                                                value2.append(formatdata(float(dataItem["casepercent"]) * 100, point))
                                            if "count" in dataItem.keys():
                                                count2.append(int(dataItem["count"]))
                                            else:
                                                if "column1" in dataItem.keys():
                                                    count2.append(int(sort_key(dataItem["column1"], None)))
                                            option2.append(dataItem["text"])
                                    if len(value1) == groupInd: value1.append(0), count1.append(0), option1.append("")
                                    if len(value2) == groupInd: value2.append(0), count2.append(0), option2.append("")
                            else:
                                for dataItem in detailValid:
                                    if str(compare[0]).strip() == str(dataItem["value"]).strip() or \
                                            str(compare[0]).strip() == str(dataItem["text"]).strip():
                                        if "count" in dataItem.keys():
                                            value1 = int(dataItem["count"])
                                        if "validpercent" in dataItem.keys():
                                            value1 = formatdata(float(dataItem["validpercent"]) * 100, point)
                                        if "casepercent" in dataItem.keys():
                                            value1 = formatdata(float(dataItem["casepercent"]) * 100, point)
                                        if "average" in dataItem.keys():
                                            value1 = formatdata(float(dataItem["average"]), point)
                                        if "textmax" in dataItem.keys():
                                            value1 = float(sort_key(str(dataItem["textmax"]), None))
                                        if "count" in dataItem.keys():
                                            count1 = int(dataItem["count"])
                                        else:
                                            if "column1" in dataItem.keys():
                                                count1 = int(sort_key(dataItem["column1"], None))
                                        option1 = dataItem["text"]
                                    elif str(compare[1]).strip() == str(dataItem["value"]).strip() or \
                                            str(compare[1]).strip() == str(dataItem["text"]).strip():
                                        if "count" in dataItem.keys():
                                            value2 = int(dataItem["count"])
                                        if "validpercent" in dataItem.keys():
                                            value2 = formatdata(float(dataItem["validpercent"]) * 100, point)
                                        if "casepercent" in dataItem.keys():
                                            value2 = formatdata(float(dataItem["validpercent"]) * 100, point)
                                        if "average" in dataItem.keys():
                                            value2 = formatdata(float(dataItem["average"]), point)
                                        if "textmax" in dataItem.keys():
                                            value2 = float(sort_key(str(dataItem["textmax"]), None))
                                        if "count" in dataItem.keys():
                                            count2 = int(dataItem["count"])
                                        else:
                                            if "column1" in dataItem.keys():
                                                count2 = int(sort_key(dataItem["column1"], None))
                                        option2 = dataItem["text"]
                        elif head["analysis"] == "crosstabs" and len(compare) > 1 and isinstance(compare[0], list) and \
                                isinstance(compare[1], list):
                            for dataItem in detailValid:
                                if str(compare[0][0]) == str(dataItem["valueRow"]) and \
                                        str(dataItem["valueColumn"]) in compare[1]:
                                    value1 += float(dataItem["validpercent"])
                                    count1 += int(dataItem["count"])
                                    option1 = dataItem["textRow"]
                                elif str(compare[0][1]) == str(dataItem["valueRow"]) and \
                                        str(dataItem["valueColumn"]) in compare[1]:
                                    value2 += float(dataItem["validpercent"])
                                    count2 += int(dataItem["count"])
                                    option2 = dataItem["textRow"]
                            value1 = formatdata(value1 * 100, point)
                            value2 = formatdata(value2 * 100, point)
                        elif head["analysis"] == "comparemeans":
                            for dataItem in detailValid:
                                if str(compare[0]) == str(dataItem["valueRow"]):
                                    value1 = formatdata(float(dataItem["average"]), point)
                                    count1 = int(dataItem["count"])
                                    option1 = dataItem["textRow"]
                                elif str(compare[1]) == str(dataItem["valueRow"]):
                                    value2 = formatdata(float(dataItem["average"]), point)
                                    count2 = int(dataItem["count"])
                                    option2 = dataItem["textRow"]
                        connectorText, percent, proportion, discriptionFrom, discriptionTo, numFrom, numTo, valueFrom, \
                        valueTo, valueCompare = "", "", "", "", "", "", "", "", "", ""
                        if connector == "": connector = ["", "", ""]
                        if len(connector) == 1: connector.append(connector[0])
                        if isinstance(value1, list):
                            if "top" in content["content"].keys():
                                value1Set, value2Set, count1Set, count2Set, option1Set, option2Set = \
                                    float(value1[0]), float(value2[0]), int(count1[0]), int(count2[0]), option1[0], \
                                    option2[0]
                                for value1Index, value1Item in enumerate(value1):
                                    if value1Index > 0:
                                        if value1Set < float(value1Item):
                                            value1Set = float(value1[value1Index])
                                            value2Set = float(value2[value1Index])
                                            count1Set = int(count1[value1Index])
                                            count2Set = int(count2[value1Index])
                                            option1Set = option1[value1Index]
                                            option2Set = option2[value1Index]
                                value1, value2, count1, count2, option1, option2 = \
                                    value1Set, value2Set, count1Set, count2Set, option1Set, option2Set
                            else:
                                discriptionFromAll, discriptionToAll, valueUnits = ["", "", ""], ["", "", ""], "【单位】"
                                if content["content"]["text"].find('%') > 0: valueUnits = '%'
                                if content["content"]["text"].find('{valueFrom}') > -1 or \
                                        content["content"]["text"].find('{valueTo}') > -1:
                                    for valueInd, valueItem in enumerate(value1):
                                        discriptionFrom, discriptionTo, numFrom, numTo = \
                                            option1[valueInd], option2[valueInd], str(count1[valueInd]), \
                                            str(count2[valueInd])
                                        valueFrom, valueTo = formatdata(float(valueItem), point), \
                                                             formatdata(float(value2[valueInd]), point)
                                        if abs(float(valueItem)) - abs(float(value2[valueInd])) > 0 or \
                                                abs(float(valueItem)) - abs(float(value2[valueInd])) < 0:
                                            if abs(float(valueItem)) - abs(float(value2[valueInd])) > 0:
                                                if discriptionToAll[0] != '': discriptionToAll[0] += '、'
                                                discriptionToAll[0] += \
                                                    formatdata(float(value2[valueInd]), point) + valueUnits
                                                connectorText = connector[0]
                                                valueCompare = formatdata(abs(float(valueItem)) -
                                                                          abs(float(value2[valueInd])), point)
                                            else:
                                                connectorText = connector[1]
                                                if discriptionToAll[1] != '': discriptionToAll[1] += '、'
                                                if connector[0] != "" and connector[0] == connector[1]:
                                                    discriptionFrom, discriptionTo, numFrom, numTo = \
                                                        option2[valueInd], option1[valueInd], str(count2[valueInd]), \
                                                        str(count1[valueInd])
                                                    valueFrom, valueTo = formatdata(float(value2[valueInd]), point), \
                                                                         formatdata(float(valueItem), point)
                                                    discriptionToAll[1] += \
                                                        formatdata(float(valueItem), point) + valueUnits
                                                else:
                                                    discriptionToAll[1] += \
                                                        formatdata(float(value2[valueInd]), point) + valueUnits
                                                valueCompare = formatdata(abs(float(value2[valueInd])) -
                                                                          abs(float(valueItem)), point)
                                            discriptionwordDict = dict(percent=percent, discriptionFrom=discriptionFrom,
                                                                       discriptionTo=discriptionTo, numFrom=numFrom,
                                                                       numTo=numTo, valueFrom=valueFrom,
                                                                       valueTo=valueTo,
                                                                       valueCompare=valueCompare,
                                                                       connector=connectorText, proportion=proportion)

                                            if abs(float(valueItem)) - abs(float(value2[valueInd])) > 0:
                                                if discriptionFromAll[0] != '': discriptionFromAll[0] += '、'
                                                discriptionFromAll[0] += \
                                                    content["content"]["text"].format(**discriptionwordDict)
                                            else:
                                                if discriptionFromAll[1] != '': discriptionFromAll[1] += '、'
                                                discriptionFromAll[1] += \
                                                    content["content"]["text"].format(**discriptionwordDict)
                                            discriptionword.append(
                                                content["content"]["text"].format(**discriptionwordDict))
                                        else:
                                            if str(connector[2]) != "":
                                                if discriptionToAll[2] != '': discriptionToAll[2] += '、'
                                                discriptionToAll[2] += \
                                                    formatdata(float(value2[valueInd]), point) + valueUnits
                                                if discriptionFromAll[2] != '': discriptionFromAll[2] += '、'
                                                if "text2" in content["content"].keys() and \
                                                        str(content["content"]["text2"]).strip() != "":
                                                    discriptionFromAll[2] += content["content"]["text2"]. \
                                                        format(percent=percent, discriptionFrom=discriptionFrom,
                                                               discriptionTo=discriptionTo, numFrom=numFrom,
                                                               numTo=numTo, valueFrom=valueFrom, valueTo=valueTo)
                                                else:
                                                    discriptionFromAll[2] += connector[2]
                                    discriptionword = discriptionFromAll
                                    for discriptionToAllIndex, discriptionToAllItem in enumerate(discriptionToAll):
                                        if discriptionToAllItem != '' and \
                                                text.find('valueTo' + str(discriptionToAllIndex + 1)) > -1:
                                            if discriptionToAllItem.find('、') > 0:
                                                discriptionwordargs["valueTo" + str(discriptionToAllIndex + 1)] = \
                                                    '（分别为' + discriptionToAllItem + '）'
                                            else:
                                                discriptionwordargs["valueTo" + str(discriptionToAllIndex + 1)] = \
                                                    '（' + discriptionToAllItem + '）'
                                        if text.find('valueTo' + str(discriptionToAllIndex + 1)) > -1 and \
                                                'valueTo' + str(discriptionToAllIndex + 1) not \
                                                in discriptionwordargs.keys():
                                            discriptionwordargs['valueTo' + str(discriptionToAllIndex + 1) + ''] = ''
                                else:
                                    discriptionFrom, discriptionTo, connectorText = \
                                        ["", "", ""], ["", "", ""], ["", "", ""]
                                    for valueInd, valueItem in enumerate(value1):
                                        if float(valueItem) - float(value2[valueInd]) > 0:
                                            if discriptionFrom[0] != "": discriptionFrom[0] += '、'
                                            discriptionFrom[0] += option1[valueInd]
                                            if discriptionTo[0] != "": discriptionTo[0] += '、'
                                            discriptionTo[0] += option2[valueInd]
                                            if connectorText[0] == "": connectorText[0] = connector[0]
                                        elif float(valueItem) - float(value2[valueInd]) < 0:
                                            if connector[0] != "" and connector[0] == connector[1]:
                                                if discriptionFrom[1] != "": discriptionFrom[1] += '、'
                                                discriptionFrom[1] += option2[valueInd]
                                                if discriptionTo[1] != "": discriptionTo[1] += '、'
                                                discriptionTo[1] += option1[valueInd]
                                                if connectorText[1] == "": connectorText[1] = connector[1]
                                            else:
                                                if discriptionFrom[1] != "": discriptionFrom[1] += '、'
                                                discriptionFrom[1] += option1[valueInd]
                                                if discriptionTo[1] != "": discriptionTo[1] += '、'
                                                discriptionTo[1] += option2[valueInd]
                                                if connectorText[1] == "": connectorText[1] = connector[1]
                                        else:
                                            if discriptionFrom[2] != "": discriptionFrom[2] += '、'
                                            discriptionFrom[2] += option1[valueInd]
                                            if discriptionTo[2] != "": discriptionTo[2] += '、'
                                            discriptionTo[2] += option2[valueInd]
                                            if connectorText[2] == "": connectorText[2] = connector[2]
                        if not isinstance(value1, list):
                            discriptionFrom, discriptionTo, numFrom, numTo = option1, option2, str(count1), str(count2)
                            valueFrom, valueTo, valueCompare = \
                                formatdata(float(value1), point), formatdata(float(value2), point), ""
                            if abs(float(value1)) - abs(float(value2)) > 0:
                                valueCompare, connectorText = \
                                    formatdata(abs(float(value1)) - abs(float(value2)), point), connector[0]
                            elif abs(float(value1)) - abs(float(value2)) < 0:
                                if connector[0] != "" and connector[0] == connector[1]:
                                    discriptionFrom, discriptionTo, numFrom, numTo = \
                                        option2, option1, str(count2), str(count1)
                                    valueFrom, valueTo = \
                                        formatdata(float(value2), point), formatdata(float(value1), point)
                                valueCompare, connectorText = \
                                    formatdata(abs(float(value2)) - abs(float(value1)), point), connector[1]
                            else:
                                if str(connector[2]) != "":
                                    if "text2" in content["content"].keys() and \
                                            str(content["content"]["text2"]).strip() != "":
                                        discriptionword.append(content["content"]["text2"].
                                                               format(percent=percent, discriptionFrom=discriptionFrom,
                                                                      discriptionTo=discriptionTo, numFrom=numFrom,
                                                                      numTo=numTo, valueFrom=valueFrom,
                                                                      valueTo=valueTo))
                                    else:
                                        discriptionword.append(connector[2])
                            if count2 > 0:
                                percent = formatdata((float(count1) / float(count2)) * 100, point)
                                proportion = formatdata((float(count1) / float(count2)), point) + "︰1"
                        if len(discriptionword) == 0:
                            if isinstance(connectorText, list):
                                for connectorTextIndex, connectorTextItem in enumerate(connectorText):
                                    if connectorTextItem != "":
                                        discriptionwordDict = dict(discriptionFrom=discriptionFrom[connectorTextIndex],
                                                                   discriptionTo=discriptionTo[connectorTextIndex],
                                                                   connector=connectorTextItem)
                                        if connectorTextIndex == 2 and "text2" in content["content"].keys() and \
                                                str(content["content"]["text2"]).strip() != "":
                                            discriptionword.append(content["content"]["text2"].
                                                                   format(**discriptionwordDict))
                                        else:
                                            discriptionword.append(content["content"]["text"].
                                                                   format(**discriptionwordDict))
                            else:
                                discriptionwordDict = dict(percent=percent, discriptionFrom=discriptionFrom,
                                                           discriptionTo=discriptionTo, numFrom=numFrom, numTo=numTo,
                                                           valueFrom=valueFrom, valueTo=valueTo,
                                                           valueCompare=valueCompare,
                                                           connector=connectorText, proportion=proportion)
                                discriptionword.append(content["content"]["text"].format(**discriptionwordDict))
                    if len(discriptionword) < 20:
                        for discriptionIndex in range(20 - len(discriptionword)):
                            discriptionword.append("")
                    if len(discriptionwordargs) > 0:
                        text = text.format(*discriptionword, **discriptionwordargs)
                    else:
                        text = text.format(*discriptionword)
                    text = replacetext(text, replaceText)
                    if text == '' or len(discriptionword) == 0: text = noDescription
                    elif ai_polishing.strip() != "":
                        contentStr = text + '\n' + ai_polishing
                        text = deepSeekai_description(contentStr)
                elif "question_title_ai" in content["content"].keys():
                    contentStr, detailValidDiscription, valueIndex, textRowSave = '', [], 99999, ''
                    if "questionnaire_theme_ai" in content["content"].keys():
                        contentStr += content["content"]["questionnaire_theme_ai"] + '\n'
                    if "question_title_ai" in content["content"].keys():
                        contentStr += content["content"]["question_title_ai"] + '\n'
                    contentStr += content["content"]["question_title_ai"] + '\n'
                    if 'valueRow' in detailValid[0].keys():
                        detailValid.sort(key=lambda x: float(x["valueRow"]), reverse=False)
                    for detailValidItem in detailValid:
                        count, discriptionKey, discriptionValue = None, [], []
                        if 'count' in detailValidItem.keys(): count = detailValidItem['count']
                        if 'text' in detailValidItem.keys():
                            discriptionKey.append('text'), discriptionValue.append(detailValidItem['text'])
                            discriptionKey.append('count'), discriptionValue.append(count)
                        elif 'textRow' in detailValidItem.keys() and 'textColumn' not in detailValidItem.keys():
                            discriptionKey.append('text'), discriptionValue.append(detailValidItem['textRow'])
                            discriptionKey.append('count'), discriptionValue.append(count)
                        elif 'textRow' in detailValidItem.keys() and 'textColumn' in detailValidItem.keys():
                            if textRowSave != '' and textRowSave != detailValidItem['textRow']:
                                valueIndex -= 1
                            discriptionKey.append('value'), discriptionValue.append(valueIndex)
                            discriptionKey.append('textRow'), discriptionValue.append(detailValidItem['textRow'])
                            discriptionKey.append('textColumn'), discriptionValue.append(
                                detailValidItem['textColumn'])
                            discriptionKey.append('count'), discriptionValue.append(count)
                            textRowSave = detailValidItem['textRow']
                        if 'average' in detailValidItem.keys():
                            discriptionKey.append('average')
                            if detailValidItem['average'] is None: detailValidItem['average'] = 0
                            discriptionValue.append(formatdata(detailValidItem['average'], point))
                        elif 'casepercent' in detailValidItem.keys():
                            discriptionKey.append('percentage')
                            if detailValidItem['casepercent'] is None: detailValidItem['casepercent'] = 0
                            discriptionValue.append(formatdata(detailValidItem['casepercent'] * 100, point))
                        elif 'validpercent' in detailValidItem.keys():
                            discriptionKey.append('percentage')
                            if detailValidItem['validpercent'] is None: detailValidItem['validpercent'] = 0
                            discriptionValue.append(formatdata(detailValidItem['validpercent'] * 100, point))
                        wordHeadFlag = []
                        if isinstance(wordHead, list) and len(wordHead) > 2:
                            for wordHeadIndex, wordHeadItem in enumerate(wordHead):
                                if wordHeadIndex > 0 and wordHeadItem == '列' + str(wordHeadIndex):
                                    wordHeadFlag.append(False)
                                else:
                                    wordHeadFlag.append(True)
                        if isinstance(wordHead, list) and len(wordHeadFlag) > 0 and \
                                all(wordHeadFlagItem is True for wordHeadFlagItem in wordHeadFlag):
                            for wordHeadIndex in range(len(wordHeadFlag) - 1):
                                wordHeadIndexStr = ''
                                discriptionKey.clear(), discriptionValue.clear()
                                if textRowSave != '' and textRowSave != detailValidItem['text']:
                                    valueIndex -= 1
                                discriptionKey.append('value'), discriptionValue.append(valueIndex)
                                discriptionKey.append('textRow')
                                discriptionValue.append(detailValidItem['text'])
                                textRowSave = detailValidItem['text']
                                discriptionKey.append('textColumn'), discriptionValue.append(
                                    wordHead[wordHeadIndex + 1])
                                if wordHeadIndex > 0:
                                    wordHeadIndexStr = str(wordHeadIndex)
                                if 'average' in detailValidItem.keys():
                                    discriptionKey.append('average')
                                    if detailValidItem['average' + wordHeadIndexStr] is None:
                                        detailValidItem['average' + wordHeadIndexStr] = 0
                                    discriptionValue.append(formatdata(
                                        detailValidItem['average' + wordHeadIndexStr], point))
                                elif 'casepercent' in detailValidItem.keys():
                                    discriptionKey.append('percentage')
                                    if detailValidItem['casepercent' + wordHeadIndexStr] is None:
                                        detailValidItem['casepercent' + wordHeadIndexStr] = 0
                                    discriptionValue.append(formatdata(
                                        detailValidItem['casepercent' + wordHeadIndexStr] * 100, point))
                                elif 'validpercent' in detailValidItem.keys():
                                    discriptionKey.append('percentage')
                                    if detailValidItem['validpercent' + wordHeadIndexStr] is None:
                                        detailValidItem['validpercent' + wordHeadIndexStr] = 0
                                    discriptionValue.append(formatdata(
                                        detailValidItem['validpercent' + wordHeadIndexStr] * 100, point))
                                detailValidDiscription.append(dict(zip(discriptionKey, discriptionValue)))
                        else:
                            detailValidDiscription.append(dict(zip(discriptionKey, discriptionValue)))
                    if 'average' in detailValidDiscription[0].keys():
                        detailValidDiscription.sort(key=lambda x: float(x["average"]), reverse=True)
                    elif 'percentage' in detailValidDiscription[0].keys():
                        if 'value' in detailValidDiscription[0].keys():
                            detailValidDiscription.sort(key=lambda x: (x["value"], float(x["percentage"])),
                                                        reverse=True)
                        else:
                            detailValidDiscription.sort(key=lambda x: float(x["percentage"]), reverse=True)
                    contentStr += str(detailValidDiscription) + '\n'
                    contentStr += content["content"]["regulation_ai"]
                    aiFlag = False
                    for slide in documentPptx.slides:
                        text_shapes, chart_shapes, table_shapes = [], [], []
                        for shape in slide.shapes:
                            iter_shape(shape, text_shapes, chart_shapes, table_shapes)
                        for shape in text_shapes:
                            if str(shape.text).find(title) > -1:
                                aiFlag = True
                                break
                    if not aiFlag:
                        text = ''
                    else:
                        text = deepSeekai_description(contentStr)
                        text = text.replace('\n\n', '\n').replace(' **', '').replace('**', '')
                        textGroup = text.split('\n')
                        for textGroupIndex, textGroupItem in enumerate(textGroup):
                            textGroupItem = textGroupItem.strip()
                            if textGroupItem[:1] == '-':
                                textGroupItem = textGroupItem[1:len(textGroupItem)]
                                textGroupItem = textGroupItem.strip()
                            textGroupItem = textGroupItem.replace('**', '').replace('*', '')
                            if textGroupIndex == 0:
                                text = textGroupItem
                            else:
                                text += '\n' + textGroupItem
                else:
                    phrase = content["content"]["phrase"]
                    for phraseItem in phrase:
                        group = phraseItem["group"]
                        percent, count, casepercent, name, average, optionID, optionNM = \
                            float(0), 0, float(0), "", float(0), "value", "text"
                        if head["analysis"] == "comparemeans":
                            optionID, optionNM = "valueRow", "textRow"
                        if connector == "": connector = "或"
                        if isinstance(group, list):
                            for ind, groupItem in enumerate(group):
                                for dataItem in detailValid:
                                    if str(groupItem).strip() == str(dataItem[optionID]).strip() or \
                                            str(groupItem).strip() == str(dataItem[optionNM]).strip():
                                        count += int(dataItem["count"])
                                        if "validpercent" in dataItem.keys():
                                            if pointGroup == "":
                                                percent += float(dataItem["validpercent"])
                                            else:
                                                percent += float(str(formatdata(float(dataItem["validpercent"]),
                                                                                int(pointGroup) + 2)))
                                        if "casepercent" in dataItem.keys():
                                            if pointGroup == "":
                                                casepercent += float(dataItem["casepercent"])
                                            else:
                                                casepercent += float(str(formatdata(float(dataItem["casepercent"]),
                                                                                    int(pointGroup) + 2)))
                                        if "average" in dataItem.keys():
                                            if pointGroup == "":
                                                average += float(dataItem["average"])
                                            else:
                                                average += float(str(formatdata(float(dataItem["average"]),
                                                                                int(pointGroup))))
                                        if name != "":
                                            name += connector
                                        name += "“" + str(dataItem[optionNM]).strip() + "”"
                        else:
                            for detailValidItem in detailValid:
                                if str(group).strip() == str(detailValidItem[optionID]).strip() or \
                                        str(group).strip() == str(detailValidItem[optionNM]).strip():
                                    count += int(detailValidItem["count"])
                                    if "validpercent" in detailValidItem.keys():
                                        percent += float(detailValidItem["validpercent"])
                                    if "casepercent" in detailValidItem.keys():
                                        casepercent += float(detailValidItem["casepercent"])
                                    if "average" in detailValidItem.keys():
                                        average += float(detailValidItem["average"])
                                    name = str(detailValidItem[optionNM]).strip()

                        if "text2" in phraseItem.keys() and len(discriptionword) == 0:
                            if name == "" and str(phraseItem["text2"]).find("name") > -1:
                                discriptionword.append("")
                            else:
                                discriptionword.append(phraseItem["text2"].
                                                       format(per=str(formatdata(percent * 100, point)) + units,
                                                              caseper=str(formatdata(casepercent * 100, point)) + units,
                                                              avg=str(formatdata(average, point)),
                                                              count=count, name=name))
                        else:
                            if name == "" and str(phraseItem["text"]).find("name") > -1:
                                discriptionword.append("")
                            else:
                                discriptionword.append(phraseItem["text"].
                                                       format(per=str(formatdata(percent * 100, point)) + units,
                                                              caseper=str(formatdata(casepercent * 100, point)) + units,
                                                              avg=str(formatdata(average, point)),
                                                              count=count, name=name))
                    if len(discriptionword) < 20:
                        for discriptionIndex in range(20 - len(discriptionword)):
                            discriptionword.append("")
                    text = text.format(*discriptionword)
                    text = replacetext(text, replaceText)
                    if text == '': text = noDescription
                    elif ai_polishing.strip() != "":
                        contentStr = text + '\n' + ai_polishing
                        textAI = deepSeekai_description(contentStr)
                        if textAI is not None: text = textAI
            if head is None and title.find("【AI总结") > -1:
                if title.find("[") > -1 and title.find("]") > -1:
                    paragraphAIFlag = title.replace("[", "").replace("]", "")
                else:
                    paragraphAIFlag = title
                if paragraphAIFlag[-1] != '】':
                    paragraphAIFlagReplace = paragraphAIFlag.find("】")
                    paragraphAIFlag = paragraphAIFlag[:paragraphAIFlagReplace + 1]
                contentStr, aiFlag = "", False
                if "questionnaire_theme_ai" in content["content"].keys():
                    contentStr += content["content"]["questionnaire_theme_ai"] + '\n'
                if "question_title_ai" in content["content"].keys():
                    contentStr += content["content"]["question_title_ai"] + '\n'
                for slide in documentPptx.slides:
                    text_shapes, chart_shapes, table_shapes = [], [], []
                    for shape in slide.shapes:
                        iter_shape(shape, text_shapes, chart_shapes, table_shapes)
                    for shape in text_shapes:
                        if str(shape.text).find(paragraphAIFlag) > -1 and str(shape.text).find(title) == -1:
                            contentStr += str(shape.text).replace(paragraphAIFlag, "") + '\n'
                            shape.text = str(shape.text).replace(paragraphAIFlag, "")
                        if str(shape.text).find(title) > -1:
                            aiFlag = True
                contentStr += content["content"]["regulation_ai"]
                if not aiFlag:
                    text = ''
                else:
                    text = deepSeekai_description(contentStr)
                    text = text.replace('\n\n', '\n').replace(' **', '').replace('**', '')
                    textGroup = text.split('\n')
                    for textGroupIndex, textGroupItem in enumerate(textGroup):
                        textGroupItem = textGroupItem.strip()
                        if textGroupItem[:1] == '-':
                            textGroupItem = textGroupItem[1:len(textGroupItem)]
                            textGroupItem = textGroupItem.strip()
                        textGroupItem = textGroupItem.replace('**', '').replace('*', '').replace('###', '')
                        if textGroupIndex == 0:
                            text = textGroupItem
                        else:
                            text += '\n' + textGroupItem
        indexcount = 0
        if title != "":
            if title.find("[") > -1:
                fromtext = title
            else:
                fromtext = "[" + fromtext + title + "]"
        else:
            fromtext = "[" + fromtext + "]"
        if bookMark != "":
            if str(os.path.abspath(os.curdir)).find("core") > 0:
                filePath = os.path.abspath(os.curdir).replace("core", "pptx")
            else:
                filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
            discriptionJsonString, discriptionJsonPath = dict(discription=[], chartall=[]), \
                                                       os.path.join(filePath, 'charts', discriptionJson)
            if os.path.exists(discriptionJsonPath):
                with open(discriptionJsonPath, "r", encoding="utf-8") as f:
                    discriptionJsonString = json.load(f)
                    f.close()
            discriptionJsonString["discription"].append(dict(bookMark="PO_" + bookMark, style=style, text=text))
            with open(discriptionJsonPath, "w", encoding="utf-8") as fp:
                fp.write(json.dumps(discriptionJsonString, indent=4))
                fp.close()
            return None

        for slide in documentPptx.slides:
            text_shapes, chart_shapes, table_shapes = [], [], []
            for shape in slide.shapes:
                iter_shape(shape, text_shapes, chart_shapes, table_shapes)
            for shape in text_shapes:
                for runIndex in range(20):
                    if str(shape.text).find(fromtext) > -1:
                        if str(shape.text).strip() == fromtext and text.find('\n') > -1 or \
                                str(shape.text).strip() == fromtext and text.find('\\n') > -1:
                            text = text.replace('\\n', '\n')
                            textGroup = text.split('\n')
                            for textIndex, textItem in enumerate(textGroup):
                                if textIndex == len(textGroup) - 1:
                                    shape.text = str(shape.text).replace(fromtext, textItem)
                                else:
                                    paragraph = shape.text_frame.add_paragraph()
                                    paragraph.text = textItem
                        else:
                            for paragraph in shape.text_frame.paragraphs:
                                discriptionRun(paragraph.runs, fromtext, text, None)
                        indexcount += 1
                        if indexcount >= countbreak and fromtext not in tableDiscription:
                            if text == noDescription and slideDelete is not None:
                                for slideDeleteItem in slideDelete:
                                    if fromtext in slideDeleteItem['text_shapes_title']:
                                        slideDeleteItem['text_shapes_title'].remove(fromtext)
                            return None
                    else:
                        break
        if fromtext in tableDiscription:
            for tableDiscriptionIndex, tableDiscriptionItem in enumerate(tableDiscription):
                if fromtext == tableDiscriptionItem:
                    for slideIndex, slide in enumerate(documentPptx.slides):
                        if slideIndex == tableIndexDiscription[tableDiscriptionIndex]:
                            for shape in slide.shapes:
                                if shape.has_table:
                                    activeTable = shape.table
                                    for tableRowIndex in range(len(activeTable.rows)):
                                        for tableColIndex in range(len(activeTable.columns)):
                                            try:
                                                if str(activeTable.cell(tableRowIndex,tableColIndex).text).find(
                                                        fromtext) > -1:
                                                    if text.find('|') > -1:
                                                        textArray = text.split('|')
                                                        table_cell_set(activeTable, tableRowIndex, tableColIndex,
                                                                       tableRowIndex, textArray[0], fromtext)
                                                        for colIndex in range(1, len(textArray)):
                                                            table_cell_set(activeTable, tableRowIndex, tableColIndex +
                                                                           colIndex, tableRowIndex, textArray[colIndex])
                                                    else:
                                                        table_cell_set(activeTable, tableRowIndex, tableColIndex,
                                                                       tableRowIndex, text, fromtext)
                                            except Exception as e:
                                                pass
        if text == noDescription and slideDelete is not None:
            for slideDeleteItem in slideDelete:
                if fromtext in slideDeleteItem['text_shapes_title']:
                    slideDeleteItem['text_shapes_title'].remove(fromtext)
    else:
        if isinstance(replaceText, list):
            if len(replaceText) == 1:replaceText.append(replaceText[0])
            replaceFrom = replaceText[0]
            replaceTo = replaceText[1]
            for replaceFromIndex, replaceFromItem in enumerate(replaceFrom):
                fromtext,text = str(replaceFromItem).strip(), ""
                if replaceFromIndex < len(replaceTo):text = str(replaceTo[replaceFromIndex])
                for slide in documentPptx.slides:
                    text_shapes, chart_shapes, table_shapes = [], [], []
                    for shape in slide.shapes:
                        iter_shape(shape, text_shapes, chart_shapes, table_shapes)
                    for shape in text_shapes:
                        for replaceIndex in range(20):
                            if str(shape.text).find(fromtext) > -1:
                                deleteFlag, fromtext_new, text_new, colorText = \
                                    textCompareReturn(fromtext, text, shape.text)
                                if deleteFlag:
                                    shape.element.getparent().remove(shape.element)
                                    break
                                else:
                                    if colorText is not None:
                                        for paragraph in shape.text_frame.paragraphs:
                                            discriptionRun(paragraph.runs, fromtext_new[len(fromtext_new) - 1], '',
                                                           None, colorText)
                                    else:
                                        for fromtext_newIndex, fromtext_newItem in enumerate(fromtext_new):
                                            for paragraph in shape.text_frame.paragraphs:
                                                discriptionRun(paragraph.runs, fromtext_newItem,
                                                               text_new[fromtext_newIndex], None, None)
                            else:
                                break
    return None


def discriptionwordLowReturn(content, head, detailValid, outColumn, point, connector):
    discriptionword, textRow, textColumn = [], '', ''
    numFrom, numStep = len(detailValid) - 1, -1
    numTo = len(detailValid) - 1 - textEqualReturn(outColumn, detailValid, point, len(detailValid) - 1)
    for num in range(numFrom, numTo, numStep):
        if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                head["analysis"] == "crosstabsSort":
            if isinstance(detailValid[num]["textColumn"], list):
                optionname = ""
                for textItem in detailValid[num]["textColumn"]:
                    optionname += str(textItem).strip()
            else:
                optionname = detailValid[num]["textColumn"]
            if isinstance(detailValid[num]["textRow"], list):
                textRow = ""
                for textItem in detailValid[num]["textRow"]:
                    textRow += str(textItem).strip()
            else:
                textRow = detailValid[num]["textRow"]
        elif head["analysis"] == "comparemeans":
            if isinstance(detailValid[num]["textRow"], list):
                optionname = ""
                for textItem in detailValid[num]["textRow"]:
                    optionname += str(textItem).strip()
            else:
                optionname = detailValid[num]["textRow"]
        else:
            if "text" in detailValid[num].keys():
                if "optiontext" in detailValid[num].keys():
                    optionname = detailValid[num]["optiontext"]
                else:
                    if isinstance(detailValid[num]["text"], list):
                        optionname = ""
                        for textItem in detailValid[num]["text"]:
                            optionname += str(textItem).strip()
                    else:
                        optionname = detailValid[num]["text"]
            else:
                optionname = ''
        percent, casepercent, average, passRate, masteryRate, percentileRank, count, outColumnFlag, \
        outColumnList, sum, columnComplete = [""], [""], [""], "", "", "", [0], False, False, [""], []
        columnName = ['validpercent', 'casepercent', 'average', 'sum', 'count', 'passRate',
                      'masteryRate', 'percentileRank']
        for columnIndex in range(20):
            columnIndexStr, columnIndexFlag = '', False
            if columnIndex > 0: columnIndexStr = str(columnIndex)
            for columnItem in columnName:
                if columnItem + columnIndexStr in detailValid[0].keys():
                    columnIndexFlag = True
                    if isinstance(detailValid[num][columnItem + columnIndexStr], list):
                        outColumnList = True
                        columnValue, outColumnFlag = \
                            outListValueFormat(columnItem,detailValid[num][columnItem + columnIndexStr], point)
                    else:
                        if columnItem == 'validpercent' or columnItem == 'casepercent' or \
                                columnItem == 'passRate' or columnItem == 'masteryRate' or \
                                columnItem == 'percentileRank':
                            columnValue = \
                                str(formatdata(sort_key(detailValid[num][columnItem + columnIndexStr], None) * 100,  point))
                        elif columnItem == 'count':
                            columnValue = int(str(detailValid[num][columnItem + columnIndexStr]).split('.')[0])
                        else:
                            columnValue = \
                                str(formatdata(sort_key(detailValid[num][columnItem + columnIndexStr], None), point))
                    if columnItem == 'validpercent':
                        if columnIndex == 0: percent[0] = columnValue
                        else: percent.append(columnValue)
                    elif columnItem == 'casepercent':
                        if columnIndex == 0: casepercent[0] = columnValue
                        else: casepercent.append(columnValue)
                    elif columnItem == 'passRate':
                        passRate = columnValue
                    elif columnItem == 'masteryRate':
                        masteryRate = columnValue
                    elif columnItem == 'percentileRank':
                        percentileRank = columnValue
                    elif columnItem == 'average':
                        if columnIndex == 0: average[0] = columnValue
                        else: average.append(columnValue)
                    elif columnItem == 'sum':
                        if columnIndex == 0: sum[0] = columnValue
                        else: sum.append(columnValue)
                    elif columnItem == 'count':
                        if columnIndex == 0: count[0] = columnValue
                        else: count.append(columnValue)
            if not columnIndexFlag: break
        discriptionwordDict = dict(passRate=passRate, masteryRate=masteryRate,
                                   percentileRank=percentileRank, name=optionname,
                                   nameRow=textRow, nameColumn=textColumn)
        for columnItem in columnName:
            formatValue, formatKey = [], ''
            if columnItem == 'validpercent':
                formatValue, formatKey = copy.deepcopy(percent), 'per'
            if columnItem == 'casepercent':
                formatValue, formatKey = copy.deepcopy(casepercent), 'caseper'
            if columnItem == 'average':
                formatValue, formatKey = copy.deepcopy(average), 'avg'
            if columnItem == 'sum':
                formatValue, formatKey = copy.deepcopy(sum), 'sum'
            if columnItem == 'count':
                formatValue, formatKey = copy.deepcopy(count), 'count'
            for columnIndex in range(len(formatValue)):
                columnIndexStr = ''
                if columnIndex > 0: columnIndexStr = str(columnIndex)
                discriptionwordDict[formatKey + columnIndexStr] = formatValue[columnIndex]
        if "text3" in content["content"].keys():
            contentText = content["content"]["text3"]
        else:
            if isinstance(content["content"]["text"], list) and len(content["content"]["text"]) > 0:
                if len(content["content"]["text"]) == 1:
                    contentText = content["content"]["text"][0]
                else:
                    contentText = content["content"]["text"][1]
            else:
                contentText = content["content"]["text"]
        discriptionword.append(contentText. \
                               format(**discriptionwordDict).format(**discriptionwordDict))
    discriptionwordNew = ''
    for discriptionIndex, discriptionItem in enumerate(discriptionword):
        if discriptionItem != "":
            if discriptionwordNew != "":
                if isinstance(connector, str):
                    discriptionwordNew += connector
                else:
                    if discriptionIndex == len(discriptionword) - 1:
                        discriptionwordNew += connector[1]
                    else:
                        discriptionwordNew += connector[0]
            discriptionwordNew += discriptionItem
    return discriptionwordNew


def textCompareReturn(fromText, toText, paragraphText):
    compareText, deleteFlag, returnFromText, returnToText, fromtextFirst, fromtextLast = \
        paragraphText.split(fromText), False, [copy.deepcopy(fromText)], [copy.deepcopy(toText)], fromText[0], \
        fromText[len(fromText) - 1]
    colorText = None
    if len(compareText) > 1 and str(toText).strip() == '删除':
        last_index = compareText[0].index(fromtextFirst)
        compareText[0] =compareText[0][last_index + 1:]
        last_index = compareText[1].index(fromtextLast)
        compareText[1] = compareText[1][:last_index]
        returnFromText = [fromtextFirst + compareText[0] + fromText + compareText[1] + fromtextLast]
        compareText[0] = compareText[0].replace('零', '0').replace('一', '1').replace('两', '2').replace('三', '3')
        compareText[1] = compareText[1].replace('零', '0').replace('一', '1').replace('两', '2').replace('三', '3')
        returnToText = ['']
        if is_number(compareText[0]) and is_number(compareText[1]):
            if fromText.find('大于等于') > -1:
                if not float(compareText[0]) >= float(compareText[1]):
                    deleteFlag = True
            elif fromText.find('小于等于') > -1:
                if not float(compareText[0]) <= float(compareText[1]):
                    deleteFlag = True
            elif fromText.find('大于') > -1:
                if not float(compareText[0]) > float(compareText[1]):
                    deleteFlag = True
            elif fromText.find('小于') > -1:
                if not float(compareText[0]) < float(compareText[1]):
                    deleteFlag = True
            elif fromText.find('等于') > -1:
                if not float(compareText[0]) == float(compareText[1]):
                    deleteFlag = True

    if paragraphText.find(fromText) > -1 and fromText.find('】') > -1 and fromText.find('【') == -1 and \
            paragraphText.find('【') > -1:
        if str(toText).strip() == '全部删除':
            positions = [index for index, char in enumerate(paragraphText) if char == '【']
            positionsNearly = -1
            for positionsItem in positions:
                if positionsNearly < positionsItem < paragraphText.find(fromText):
                   positionsNearly = positionsItem
            returnFromText = [paragraphText[positionsNearly:paragraphText.find(fromText) + len(fromText)]]
            if paragraphText == returnFromText[0]:
                deleteFlag = True
            returnToText = ['']
        else:
            returnFromText, returnToText =['【', fromText], ['', '']
            if fromText.find('颜色') > -1:
                colorText = toText
    return deleteFlag, returnFromText, returnToText, colorText


def chatai_description(detailValidContent):
    # 设置你的 OpenAI API 密钥
    api_key = 'sk-7fN9qAejjbDaLE1QLwS40MXOaHmScEkUAmmeE3oEdMy82QWk'
    # 设置请求头
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {api_key}'
    }
    # 初始化对话历史
    conversation_history = []

    # 将当前输入添加到对话历史
    conversation_history.append({"role": "user", "content": detailValidContent})

    # 准备请求数据
    data = {
        "model": "gpt-3.5-turbo",
        "messages": conversation_history,
        "temperature": 0.7
    }
    # 发送请求到 OpenAI API
    response = requests.post('https://api.chatanywhere.tech/v1/chat/completions', headers=headers, data=json.dumps(data))
    # 检查请求是否成功
    if response.status_code == 200:
        result = response.json()
        # 获取模型回复
        reply = result['choices'][0]['message']['content']
        # 将回复添加到对话历史
        conversation_history.append({"role": "assistant", "content": reply})
        return reply
    else:
        return None


def deepSeekai_description(detailValidContent):
    try:
        from openai import OpenAI
        client = OpenAI(
            # 若没有配置环境变量，请用阿里云百炼API Key将下行替换为：api_key="sk-xxx",
            api_key="sk-5e35f755c09f43c9a06e6ea6fcc93e79",
            # 如何获取API Key：https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key
            base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
        )
        messages = [
            {'role': 'user', 'content': detailValidContent}
        ]
        completion = client.chat.completions.create(
            model="deepseek-v3",  # 此处以 deepseek-r1 为例，可按需更换模型名称。
            messages=messages
        )
        return completion.choices[0].message.content
    except Exception as e:
        return None


def baiduai_description(detailValidContent):
    try:
        url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=" + \
              get_access_token()
        payload = json.dumps({"messages": [{"role": "user", "content": detailValidContent}]})
        headers = {'Content-Type': 'application/json'}
        response = requests.request("POST", url, headers=headers, data=payload)
        return json.loads(response.text)['result']
    except Exception as e:
        return None


def get_access_token():
    """
    使用 API Key，Secret Key 获取access_token，替换下列示例中的应用API Key、应用Secret Key
    """
    api_key = 'gs0JSnGqIRUUHSPtprGoJksK'
    secret_key = 'Ao7WrrqwvzxWD6wOAM3Dx41Wo6TgmxmW'
    url = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + api_key
    url += "&client_secret=" + secret_key

    #payload = {"prompt": 'analy描述'}
    payload = {}
    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }

    response = requests.request("POST", url, headers=headers, data=payload)
    return response.json().get("access_token")


def textEqualReturn(outColumn, detailValid, point, indexStar):
    equalReturn = 1
    if indexStar == 0:
        numFrom = indexStar + 1
        numTo = len(detailValid)
        numStep = 1
    else:
        numFrom = indexStar - 1
        numTo = -1
        numStep = -1
    for num in range(numFrom, numTo, numStep):
        if outColumn == "validpercent" or outColumn == "casepercent":
            if float(str(formatdata(sort_key(detailValid[indexStar][outColumn], None) * 100, point))) == \
                    float(str(formatdata(sort_key(detailValid[num][outColumn], None) * 100, point))):
                equalReturn += 1
            else:
                break
        else:
            if float(str(formatdata(sort_key(detailValid[indexStar][outColumn], None), point))) == \
                    float(str(formatdata(sort_key(detailValid[num][outColumn], None), point))):
                equalReturn += 1
            else:
                break
    return equalReturn


def iter_shape(shape, text_shapes, chart_shapes, table_shapes):
    if shape.shape_type == MSO_SHAPE_TYPE.GROUP:
        for sshape in shape.shapes:
            iter_shape(sshape, text_shapes, chart_shapes, table_shapes)
    else:
        if shape.has_text_frame:
            text_shapes.append(shape)
        if shape.has_chart:
            chart_shapes.append(shape)
        if shape.has_table:
            table_shapes.append(shape)


def outListValueFormat(outColumnName, outColumnValue, point):
    outListValueFormatStr, unit, outColumnFlag = '', '%', False
    if outColumnName == 'average' or outColumnName == 'sum' or outColumnName == 'count':unit= ''
    for outColumnValueItem in outColumnValue:
        if outListValueFormatStr != '':
            outListValueFormatStr += '、'
            outColumnFlag = True
        if outColumnName == 'count':
            outListValueFormatStr += int(str(outColumnValueItem).split('.')[0])
        elif outColumnName == 'average' or outColumnName == 'sum':
            outListValueFormatStr += str(formatdata(sort_key(outColumnValueItem, None), point))
        else:
            outListValueFormatStr += str(formatdata(sort_key(outColumnValueItem, None) * 100, point)) + unit
    return outListValueFormatStr, outColumnFlag


def detailValidOrderReset(head, detailValid, wordHead, outColumn, sort, originalTop, point):
    itemCount = ''
    for detailValidItem in detailValid[0].keys():
        if detailValidItem.find(outColumn) > -1 and detailValidItem != 'orderAverage':
            itemCount = detailValidItem.replace(outColumn, '')
    if itemCount != '':
        wordHeadFlag = []
        if isinstance(wordHead, list) and len(wordHead) > 2:
            for wordHeadIndex,wordHeadItem in enumerate(wordHead):
                if wordHeadIndex > 0 and wordHeadItem == '列' + str(wordHeadIndex):
                    wordHeadFlag.append(False)
                else:
                    wordHeadFlag.append(True)
        if len(wordHeadFlag) > 0 and all(wordHeadFlagItem is True for wordHeadFlagItem in wordHeadFlag):
            detailValidReset = []
            for itemCountIndex in range(0, int(itemCount) + 1):
                if itemCountIndex == 0:
                    itemCountIndexStr = ''
                else:
                    itemCountIndexStr = str(itemCountIndex)
                if str(sort).find('-') == 0:
                    if all(sort_key(deleteItem[outColumn + itemCountIndexStr], None) == 0 for deleteItem in
                           detailValid): continue
                    detailValid.sort(key=lambda x: sort_key(x[outColumn + itemCountIndexStr], True), reverse=True)
                else:
                    if all(sort_key(deleteItem[outColumn + itemCountIndexStr], None) == 0 for deleteItem in
                           detailValid): continue
                    detailValid.sort(key=lambda x: sort_key(x[outColumn + itemCountIndexStr], False), reverse=False)
                top = returncount(detailValid, int(originalTop), outColumn + itemCountIndexStr, point)
                valueRow, textRow, valueColumn, textColumn = '', '', itemCountIndex + 1, wordHead[itemCountIndex + 1]
                for topIndex in range(top):
                    if textRow != '':
                        textRow += '、'
                    textRow += detailValid[topIndex]['text']
                    valueRow += str(detailValid[topIndex]['value'])
                detailValidFlag = False
                for detailValidResetIndex, detailValidResetItem in enumerate(detailValidReset):
                    if detailValidResetItem['textRow'] == textRow:
                        detailValidReset[detailValidResetIndex]['textColumn'] += '、'
                        detailValidReset[detailValidResetIndex]['textColumn'] += textColumn
                        detailValidReset[detailValidResetIndex][outColumn].\
                            append(sort_key(detailValid[0][outColumn + itemCountIndexStr], None))
                        detailValidFlag = True
                        break
                if not detailValidFlag:
                    detailValidReset.append({'valueRow': valueRow, 'textRow': textRow, 'valueColumn': valueColumn,
                                             'textColumn': textColumn,
                                             outColumn:[sort_key(detailValid[0][outColumn + itemCountIndexStr], None)]})
            for itemCountIndex in range(len(detailValidReset)):
                if len(detailValidReset[itemCountIndex][outColumn]) == 0:
                    detailValidReset[itemCountIndex][outColumn] = detailValidReset[itemCountIndex][outColumn][0]
            head['analysis'] = 'crosstabs'
            return head, detailValidReset, itemCount, len(detailValidReset)
        '''
        else:
            for detailValidIndex in range(len(detailValid)):
                detailValid[detailValidIndex]['orderAverage'] = len(detailValid) - detailValidIndex
            for itemCountIndex in range(1, int(itemCount) + 1):
                if str(sort).find('-') == 0:
                    detailValid.sort(key=lambda x: sort_key(x[outColumn + str(itemCountIndex)], True), reverse=True)
                else:
                    detailValid.sort(key=lambda x: sort_key(x[outColumn + str(itemCountIndex)], False), reverse=False)
                for detailValidIndex in range(len(detailValid)):
                    detailValid[detailValidIndex]['orderAverage'] = detailValid[detailValidIndex]['orderAverage'] + \
                        (len(detailValid) - detailValidIndex)
            detailValid.sort(key=lambda x: x['orderAverage'], reverse=True)
        '''
    return head, detailValid,itemCount, originalTop


def pptxdiscriptionTextAndTable(documentPptx, discriptionTitle, chartTitle, tableTitle):
    textDiscription, tableDiscription, tableIndexDiscription, slideDelete = [], [], [], []
    for slideIndex, slide in enumerate(documentPptx.slides):
        text_shapes, chart_shapes, table_shapes, text_shapes_title, chart_shapes_title, table_shapes_title = \
            [], [], [], [], [], []
        for shape in slide.shapes:
            iter_shape(shape, text_shapes, chart_shapes, table_shapes)
        for shape in text_shapes:
            shape_text = copy.deepcopy(shape.text)
            if shape_text.find('[') > -1 and shape_text.find(']') > 0:
                for discriptionItem in discriptionTitle:
                    if str(shape.text).find(discriptionItem) > -1:
                        text_shapes_title.append(discriptionItem)
                        shape_text = shape_text.replace(discriptionItem, '')
                    if not shape_text.find('[') > -1 and shape_text.find(']') > 0: break
        for shape in chart_shapes:
            for chartItem in chartTitle:
                if shape.chart.has_title and shape.chart.chart_title.text_frame.text.find(chartItem) > -1:
                    chart_shapes_title.append(chartItem)
                    break
        for shapeIndex, shape in enumerate(table_shapes):
            activeTable = shape.table
            for tableRowIndex in range(len(activeTable.rows)):
                for tableColIndex in range(len(activeTable.columns)):
                    try:
                        if str(activeTable.cell(tableRowIndex, tableColIndex).text).find('[') > -1 and \
                                str(activeTable.cell(tableRowIndex, tableColIndex).text).find( ']') > 0:
                            if not str(activeTable.cell(tableRowIndex, tableColIndex).text).find('[表') > -1:
                                paragraphs = activeTable.cell(tableRowIndex, tableColIndex).text_frame.paragraphs
                                for paragraph in paragraphs:
                                    paragraphText = str(paragraph.text)
                                    if str(paragraphText).find('[') > -1 and str(paragraphText).find(']') > 0:
                                        for paragraphTextIndex in range(len(paragraphText)):
                                            fromText = paragraphText[paragraphText.find('['):paragraphText.find(']') + 1]
                                            tableDiscription.append(fromText)
                                            tableIndexDiscription.append(slideIndex)
                                            paragraphText = paragraphText.replace(fromText, '')
                                            if fromText in discriptionTitle: text_shapes_title.append(fromText)
                                            if not (str(paragraphText).find('[') > -1 and str(paragraphText).find(']') > 0):
                                                break
                            else:
                                paragraphText = activeTable.cell(tableRowIndex, tableColIndex).text
                                fromText = paragraphText[paragraphText.find('['):paragraphText.find(']') + 1]
                                if fromText in tableTitle: table_shapes_title.append(fromText)
                    except Exception as e:
                        pass
        slideDelete.append(dict(slideIndex=slideIndex, text_shapes_title=text_shapes_title,
                                text_shapes_count=len(text_shapes_title), chart_shapes_title=chart_shapes_title,
                                chart_shapes_count=len(chart_shapes_title), table_shapes_title=table_shapes_title,
                                table_shapes_count=len(table_shapes_title)))
    return textDiscription, tableDiscription, tableIndexDiscription, slideDelete


def pptxdiscriptionText(textDiscription, wordtextAll):
    textString, textStringLeft, textStringRight, textStringSave, textStringGroup, textStringSaveGroup = \
        "", "", "", [], [], []
    for ci in wordtextAll.iter():
        if ci.text is not None:
            if str(ci.text).find('[') > -1:
                textStringLeft += '['
                textStringRight += ']'
            if str(ci.text) not in textStringSave and not (textString == '' and str(ci.text) == ']') or \
                    (textString.find(str(ci.text)) < 0 and textString != '' and str(ci.text) == ']'):
                textString += str(ci.text)
            textStringSave.append(ci.text)
            if textString.find('[') > -1 and textString.find(']') > 0:
                textStringGroup.append(textString)
                textString = ''
                textStringSaveGroup.extend(textStringSave)
                textStringSave.clear()
    for textString in textStringGroup:
        if len(textStringLeft) == len(textStringRight) and textString.find('[') > -1 and \
                textString.find(']') > 0:
            fromText = textString[textString.find('['):textString.find(']') + 1]
            fromTextFlag = True
            for textDiscriptionItem in textDiscription:
                if fromText in textDiscriptionItem.keys():
                    fromTextFlag = False
                    break
            if fromTextFlag:
                wordtextIndex = None
                if 'style' in wordtextAll.attrib.keys():
                    wordtextIndex = "".join(list(filter(str.isdigit, str(wordtextAll.attrib['style']).strip())))
                textDiscription.append({fromText: [wordtextIndex, copy.deepcopy(textStringSaveGroup), 'body']})
    return textDiscription


def pptxdiscriptionReplace(documentPptx):
    replaceText, countbreak = [], 5
    replaceText.append(['此题无相关数据！！！！！，此题无相关数据！！！！！；',
                        '此题无相关数据！！！！！，此题无相关数据！！！！！。',
                        '此题无相关数据！！！！！，此题无相关数据！！！！！！',
                        '，此题无相关数据！！！！！，', '，此题无相关数据！！！！！；',
                        '，此题无相关数据！！！！！。','，此题无相关数据！！！！！！',
                        '；此题无相关数据！！！！！。', '；此题无相关数据！！！！！！',
                        '，“此题无相关数据！！！！！”，', '，“此题无相关数据！！！！！”；',
                        '，“此题无相关数据！！！！！”。','，“此题无相关数据！！！！！”！',
                        '；“此题无相关数据！！！！！”。','；“此题无相关数据！！！！！”！',
                        '，；','，。','，！','。。','，“”；','，“”。','，“”！','。“”。','“”',
                        '。“此题无相关数据！！！！！”。','。此题无相关数据！！！！！。', '““', '””'])
    replaceText.append(['','','','，','；','。','！','。','！','，','；','。','！','。','！','；','。','！','。',
                        '；','。','！','。','','。','。', '“', '”'])
    if isinstance(replaceText, list):
        if len(replaceText) == 1:replaceText.append(replaceText[0])
        replaceFrom = replaceText[0]
        replaceTo = replaceText[1]
        for replaceIndex in range(countbreak):
            replaceFlag = False
            for replaceFromIndex, replaceFromItem in enumerate(replaceFrom):
                fromtext,text = str(replaceFromItem).strip(), ""
                if replaceFromIndex < len(replaceTo):text = str(replaceTo[replaceFromIndex])
                for slide in documentPptx.slides:
                    for shape in slide.shapes:
                        if str(shape.text).find(fromtext) > -1:
                            shape.text = str(shape.text).replace(fromtext, text)
                            replaceFlag = True
            if not replaceFlag:break
    return None


def discriptionRun(paragraphRuns, fromtext, text, paragraph, colorText=None):
    runList, runText, runFlag, runListFlag, fromtextFirst, fromtextLast = \
        [], "", False, False, fromtext[0], fromtext[len(fromtext) - 1]
    fromtextFirstCount = fromtext.count(fromtextFirst)
    fromtextLastCount = fromtext.count(fromtextLast)
    for runIndex, runItem in enumerate(paragraphRuns):
        if runItem.text.find(fromtextFirst) > -1 or runFlag:
            if runItem.text.find(fromtextLast) > -1:
                runList.append(runIndex)
                runText += runItem.text
                runTextBefore = ""
                runTextAfter = ""
                if runText.find(fromtext) > -1:
                    if runText != fromtext:
                        if runText.find(fromtext) == 0:
                            runTextAfter = runText.replace(fromtext, "")
                        else:
                            runTextRetain = runText.split(fromtext)
                            runTextBefore = runTextRetain[0]
                            if len(runTextRetain) > 1: runTextAfter = runTextRetain[1]
                            if len(runTextRetain) > 2: runTextAfter += text + runTextRetain[2]
                            if len(runTextRetain) > 3: runTextAfter += text + runTextRetain[3]
                    if colorText is not None:
                        runListAgain, boldFlag = [], False
                        if colorText.find('加粗') > -1:
                            boldFlag, colorText = True, colorText.replace('加粗', '')
                        if runText.find('【') == -1:
                            for runIndexAgain, runItemAgain in enumerate(paragraphRuns):
                                if ((paragraphRuns[runIndexAgain].text.find('【') > -1 and len(runListAgain) == 0) or
                                    len(runListAgain) != 0) and runIndexAgain <= runList[0]:
                                    runListAgain.append(runIndexAgain)
                        else:
                            for runIndexAgain, runItemAgain in enumerate(paragraphRuns):
                                if runIndexAgain in runList and ((paragraphRuns[runIndexAgain].text.find('【') > -1 and
                                                                  len(runListAgain) == 0) or len(runListAgain) != 0):
                                    runListAgain.append(runIndexAgain)
                            runList = []
                        for runIndexAgain, runItemAgain in enumerate(paragraphRuns):
                            if runIndexAgain in runListAgain or runIndexAgain in runList:
                                try:
                                    if boldFlag: paragraphRuns[runIndexAgain].font.bold = True
                                    font_rgb = ImageColor.getrgb(colorText)
                                    paragraphRuns[runIndexAgain].font.color.rgb = RGBColor(font_rgb[0], font_rgb[1],
                                                                                           font_rgb[2])
                                    paragraphRuns[runIndexAgain].text = \
                                        paragraphRuns[runIndexAgain].text.replace(fromtext, '').replace('【', '')
                                except Exception as e:
                                    pass
                        break
                    for runListItem in runList:
                        paragraphRuns[runListItem].text = ""
                    if text is not None and text.find('“') > -1 and text.find('”') > -1:
                        if runList[0] > 0 and runList[len(runList) - 1] < len(paragraphRuns) - 1:
                            if paragraphRuns[runList[0] - 1].text.find('“') > -1 and \
                                    paragraphRuns[runList[len(runList) - 1] + 1].text.find('”') == 0:
                                runTextBefore = paragraphRuns[runList[0] - 1].text.replace('“', '') + runTextBefore
                                paragraphRuns[runList[len(runList) - 1] + 1].text = \
                                    paragraphRuns[runList[len(runList) - 1] + 1].text.replace('”', '')
                                for runListIndex, runListItem in enumerate(runList):
                                    runList[runListIndex] = runListItem - 1
                        if len(runList) == 1 and runTextBefore.find('“') > -1 and runTextAfter.find('”') > -1:
                            if runTextBefore.count('“') > 1:
                                last_index = runTextBefore.rindex('“')
                                runTextBefore = runTextBefore[:last_index] + runTextBefore[last_index + 1:]
                            else:
                                runTextBefore = runTextBefore.replace('“', '')
                            runTextAfter = runTextAfter.replace('”', '', 1)
                    if text is not None and text.find('】') > -1 and text.find('【') > -1 and text.find('颜色') > -1 \
                            and paragraph is not None:
                        textGroup, runStar, runEnd = [], 0, 0
                        while len(text) > 0:
                            if text.find('【') == 0:
                                textGroup.append(text[0: text.find('】') + 1])
                                text = text[text.find('】') + 1:len(text)]
                            elif text.find('【') > 0:
                                textGroup.append(text[0: text.find('【')])
                                textGroup.append(text[text.find('【'): text.find('】') + 1])
                                text = text[text.find('】') + 1:len(text)]
                            else:
                                textGroup.append(text)
                                text = ''
                        for runAddIndex in range(len(runList), len(textGroup)):
                            paragraph.add_run()
                        if runTextBefore != '':
                            paragraph.add_run()
                            runStar = 1
                        if runTextAfter != '':
                            paragraph.add_run()
                            runEnd = 1
                        paragraphRuns = paragraph.runs
                        for runAddIndex in range(len(paragraph.runs) - 1, runList[len(runList) - 1], -1):
                            paragraphRuns[runAddIndex].text = paragraphRuns[runAddIndex - 1].text
                        if runTextBefore != '': paragraphRuns[runList[0]].text = runTextBefore
                        if runTextAfter != '': paragraphRuns[runList[0] + len(textGroup) - 1].text = runTextAfter
                        for runAddIndex in range(runList[0] + runStar, runList[0] + len(textGroup) - runEnd):
                            paragraphRuns[runAddIndex].text = textGroup[runAddIndex - runList[0] - runStar]
                    else:
                        if len(runList) == 1:
                            paragraphRuns[runList[0]].text = runTextBefore + str(text) + runTextAfter
                        else:
                            if runTextBefore != "":
                                paragraphRuns[runList[0]].text = runTextBefore + str(text)
                            else:
                                paragraphRuns[runList[0]].text = text
                            paragraphRuns[runList[len(runList) - 1]].text = runTextAfter
                    break
                else:
                    if runItem.text.count(fromtextFirst) == fromtextFirstCount and \
                            runItem.text.count(fromtextLast) == fromtextLastCount and \
                            runItem.text.index(fromtextFirst) < runItem.text.index(fromtextLast):
                        runList, runText, runFlag = [], "", False
                    elif runItem.text.count(fromtextFirst) == fromtextFirstCount:
                        runList = [runIndex]
                        runText = runItem.text
                        runFlag = True
                    elif runItem.text.find(fromtextLast) > -1:
                        runFlag = True
                    else:
                        runList, runText, runFlag = [], "", False
                    runTextCheck = ''
                    for runListItem in runList:
                        runTextCheck += paragraphRuns[runListItem].text
                    fromtextCount = [index for index, char in enumerate(runTextCheck) if char == fromtextFirst]
                    if runTextCheck.find(fromtextFirst) > -1 and runTextCheck.find(fromtextLast) > -1 and \
                            runTextCheck.find(fromtextLast) - runTextCheck.find(fromtextFirst) > 1 and \
                            runTextCheck.find(fromtext) == -1 and \
                            not all(item < runTextCheck.find(fromtextLast) for item in fromtextCount):
                        runList = []
                        runText = ''
                        runFlag = False
                        if runItem.text.find(fromtextFirst) > -1 and runItem.text.find(fromtextLast) > -1:
                            runList = [runIndex]
                            runText = runItem.text
                            runFlag = True
            else:
                runList.append(runIndex)
                runText += runItem.text
                runFlag = True
    # 重复标点符号处理
    punctuation_repeat = ['、', '，', '；', '。', '！', '？']
    for runIndex, runItem in enumerate(paragraphRuns):
        if runItem.text != '' and str(runItem.text).find('此题无相关数据！！！！！') < 0 and \
                runItem.text[len(runItem.text) - 1:len(runItem.text)] in punctuation_repeat:
            runIndexEnd = 0
            punctuationStar = punctuation_repeat.index(runItem.text[len(runItem.text) - 1:len(runItem.text)])
            for runIndexCount in range(runIndex + 1, len(paragraphRuns)):
                if paragraphRuns[runIndexCount].text != '' and \
                        paragraphRuns[runIndexCount].text[0:1] in punctuation_repeat:
                    if punctuationStar <= punctuation_repeat.index(paragraphRuns[runIndexCount].text[0:1]):
                        if paragraphRuns[runIndex].text in punctuation_repeat:
                            paragraphRuns[runIndex].text = ''
                        else:
                            paragraphRuns[runIndex].text = paragraphRuns[runIndex].text[0: len(runItem.text) - 1]
                    else:
                        if paragraphRuns[runIndexCount].text in punctuation_repeat:
                            paragraphRuns[runIndexCount].text = ''
                        else:
                            paragraphRuns[runIndexCount].text = \
                                paragraphRuns[runIndexCount].text[1: len(paragraphRuns[runIndexCount].text)]
                    runIndexEnd += 1
                if paragraphRuns[runIndexCount].text != '' and \
                        paragraphRuns[runIndexCount].text[0:1] not in punctuation_repeat:
                    break
                if runIndexEnd > 0: break
    return None


def compareReturn(comStr, valueFrom, valueTo, detailValidItem, headItem):
    returnFlag, headFlag = False, False
    if isinstance(comStr, list):
        valueGroup = []
        for comIndex in range(len(comStr)):
            if valueFrom[comIndex] == "text":valueFrom[comIndex] = "optiontext"
            if is_number(valueTo[comIndex]):
                valueToItem = float(valueTo[comIndex])
            else:
                valueToItem = valueTo[comIndex]
            if valueFrom[comIndex] in detailValidItem.keys() or valueFrom[comIndex] in headItem.keys():
                valueFromItem = None
                if valueFrom[comIndex] in headItem.keys():
                    headFlag = True
                    if headItem[valueFrom[comIndex]] is None:
                        valueFromItem = 0
                    else:
                        valueFromItem = float(headItem[valueFrom[comIndex]])
                if valueFrom[comIndex] in detailValidItem.keys():
                    headFlag = False
                    if detailValidItem[valueFrom[comIndex]] is None:
                        valueFromItem = 0
                    else:
                        valueFromItem = float(detailValidItem[valueFrom[comIndex]])
                if str(comStr[comIndex]).strip() == "=" or str(comStr[comIndex]).strip() == "==":
                    valueGroup.append(eq(valueFromItem, valueToItem))
                elif str(comStr[comIndex]).strip() == "<":
                    valueGroup.append(lt(valueFromItem, valueToItem))
                elif str(comStr[comIndex]).strip() == "<=":
                    valueGroup.append(le(valueFromItem, valueToItem))
                elif str(comStr[comIndex]).strip() == ">":
                    valueGroup.append(gt(valueFromItem, valueToItem))
                elif str(comStr[comIndex]).strip() == ">=":
                    valueGroup.append(ge(valueFromItem, valueToItem))
                elif str(comStr[comIndex]).strip() == "!=" or str(comStr[comIndex]).strip() == "<>":
                    valueGroup.append(ne(valueFromItem, valueToItem))
                elif str(comStr[comIndex]).strip() == "in":
                    if str(detailValidItem[valueFrom[comIndex]]).strip() in valueToItem:
                        valueGroup.append(True)
                else:
                    valueGroup.append(None)
            else:
                valueGroup.append(None)
        returnFlag = True
        for valueItem in valueGroup:
            if not valueItem:
                returnFlag = False
    else:
        if is_number(valueTo):
            valueToItem = float(valueTo)
        else:
            valueToItem = valueTo
        if valueFrom == "text":valueFrom = "optiontext"
        if valueFrom in detailValidItem.keys() or valueFrom in headItem.keys():
            valueFromItem = None
            if valueFrom in headItem.keys():
                headFlag = True
                if headItem[valueFrom] is None:
                    valueFromItem = 0
                else:
                    valueFromItem = float(headItem[valueFrom])
            if valueFrom in detailValidItem.keys():
                headFlag = False
                if detailValidItem[valueFrom] is None:
                    valueFromItem = 0
                else:
                    valueFromItem = float(detailValidItem[valueFrom])
            if str(comStr).strip() == "=" or str(comStr).strip() == "==":
                returnFlag = eq(valueFromItem, valueToItem)
            elif str(comStr).strip() == "<":
                returnFlag = lt(valueFromItem, valueToItem)
            elif str(comStr).strip() == "<=":
                returnFlag = le(valueFromItem, valueToItem)
            elif str(comStr).strip() == ">":
                returnFlag = gt(valueFromItem, valueToItem)
            elif str(comStr).strip() == ">=":
                returnFlag = ge(valueFromItem, valueToItem)
            elif str(comStr).strip() == "!=" or str(comStr).strip() == "<>":
                returnFlag = ne(valueFromItem, valueToItem)
            elif str(comStr).strip() == "in":
                if str(detailValidItem[valueFrom]).strip() in valueToItem:
                    returnFlag = True
            else:
                returnFlag = None
        else:
            returnFlag = None
    return returnFlag, headFlag


def compareValueReturn(comStr, valueFrom, valueTo):
    if str(comStr).strip() == "=" or str(comStr).strip() == "==":
        if isinstance(valueTo, list):
            return eq(float(valueTo[0]), valueFrom) and eq(valueFrom, float(valueTo[1]))
        else:
            return eq(valueFrom, valueTo)
    elif str(comStr).strip() == "<":
        if isinstance(valueTo, list):
            return lt(float(valueTo[0]), valueFrom) and lt(valueFrom, float(valueTo[1]))
        else:
            return lt(valueFrom, valueTo)
    elif str(comStr).strip() == "<=":
        if isinstance(valueTo, list):
            return le(float(valueTo[0]), valueFrom) and le(valueFrom, float(valueTo[1]))
        else:
            return le(valueFrom, valueTo)
    elif str(comStr).strip() == ">":
        if isinstance(valueTo, list):
            return gt(float(valueTo[0]), valueFrom) and gt(valueFrom, float(valueTo[1]))
        else:
            return gt(valueFrom, valueTo)
    elif str(comStr).strip() == ">=":
        if isinstance(valueTo, list):
            return ge(float(valueTo[0]), valueFrom) and ge(valueFrom, float(valueTo[1]))
        else:
            return ge(valueFrom, valueTo)
    else:
        return None


def pptxcharts(documentPptx, contentRow, json_data, chartJson, allReplace, slideDelete, edition, templateId):
    content=contentRow["content"]
    datadef = lambda: None if "data" not in content.keys() else content["data"]
    pointdef = lambda:2 if "point" not in content.keys() else content["point"]
    unitsdef = lambda:"" if "units" not in content.keys() else content["units"]
    widthdef = lambda:13.83 if "width" not in content.keys() else float(content["width"])
    heightdef = lambda:6.67 if "height" not in content.keys() else float(content["height"])
    phrasedef = lambda: "" if "phrase" not in content.keys() else content["phrase"]
    chartnamedef = lambda: "" if "chartname" not in content.keys() else content["chartname"]
    dataN, point,units,width,height,phrase,chartname,chartflag = datadef(), pointdef(), unitsdef(), widthdef(), \
                                                                 heightdef(), phrasedef(), chartnamedef(), False
    titledef = lambda: "" if "title" not in content.keys() else content["title"]
    rowTextdef = lambda: "" if "rowText" not in content.keys() else content["rowText"]
    outColumndef = lambda: "" if "outColumn" not in content.keys() else content["outColumn"]
    unitsBeforedef = lambda: "" if "unitsBefore" not in content.keys() else content["unitsBefore"]
    unitsAfterdef = lambda: "" if "unitsAfter" not in content.keys() else content["unitsAfter"]
    sortFirstdef = lambda: [] if "sortFirst" not in content.keys() else content["sortFirst"]
    sortLastdef = lambda: [] if "sortLast" not in content.keys() else content["sortLast"]
    positiondef = lambda: "" if "position" not in content.keys() else content["position"]
    displayRowdef = lambda: "" if "displayRow" not in content.keys() else content["displayRow"]
    displayTextdef = lambda: "" if "displayText" not in content.keys() else content["displayText"]
    chartLabelColdef = lambda: "" if "chartLabelCol" not in content.keys() else content["chartLabelCol"]
    replaceTextdef = lambda: "" if "replaceText" not in content.keys() else content["replaceText"]
    zeroFilldef = lambda: "" if "zeroFill" not in content.keys() else str(content["zeroFill"])
    phraseDatadef = lambda: "" if "phraseData" not in content.keys() else content["phraseData"]
    colEnddef = lambda: "" if "colEnd" not in content.keys() else content["colEnd"]
    pointGroupdef = lambda: "" if "pointGroup" not in content.keys() else content["pointGroup"]
    title, rowText, outColumn, unitsBefore, unitsAfter, fromtext, detailValid, columnMax, chartLabelCol = \
        titledef(), rowTextdef(), outColumndef(), unitsBeforedef(), unitsAfterdef(), "图", [], 0, chartLabelColdef()
    sortFirst, sortLast, position, displayRow, displayText, replaceText, zeroFill, phraseData, columnStringBack = \
        sortFirstdef(), sortLastdef(), positiondef(), displayRowdef(), displayTextdef(), replaceTextdef(), \
        zeroFilldef(), phraseDatadef(), {}
    colEnd, pointGroup, columnNameCheck = colEnddef(), pointGroupdef(), []
    if position == '[图12]':
        testFlag = True
    if allReplace is not None:
        if isinstance(replaceText, str) and replaceText == "":
            replaceText = allReplace
        else:
            if isinstance(replaceText, list):
                for replace in allReplace[0]:
                    replaceText[0].append(replace)
                for replace in allReplace[1]:
                    replaceText[1].append(replace)
    if len(sortFirst) == 0 and len(sortLast) == 0:
        rowNo, sortAll = 0, []
    else:
        if len(sortFirst) != 0:
            rowNo, sortAll = -99999, sortFirst
        else:
            rowNo, sortAll = 99999, sortLast
    if rowText != "":
        detailValidTotal, sumColumnFlag = rowDataProcess(outColumn, rowText, phrase, "", rowNo, sortAll, json_data,
                                                         False, phraseData, pointGroup, "")
        for detailValidTotalItem in detailValidTotal:
            if len(detailValid) == 0:
                detailValid = detailValidTotalItem
            else:
                max_value = max(detailValidItem['value'] for detailValidItem in detailValid)
                for detailValidItem in detailValidTotalItem:
                    new_detailValidItem = [{k: (v + max_value) if k == 'value' else v for k, v in detailItem.items()}
                                           for detailItem in detailValidItem]
                    detailValid.append(new_detailValidItem)
        for detailItem in detailValid:
            if detailItem["columnMax"] > columnMax: columnMax = detailItem["columnMax"]
    else:
        for columnIndex in range(len(outColumn)):
            detailValid.append(dict(value=int(columnIndex + 1)))
            chartPoint = ''
            if isinstance(pointGroup, list) and columnIndex < len(pointGroup): chartPoint = pointGroup[columnIndex]
            if isinstance(outColumn[columnIndex], list):
                if len(outColumn[columnIndex]) > columnMax: columnMax = len(outColumn[columnIndex])
                for indexCol in range(len(outColumn[columnIndex])):
                    if columnIndex == 0 and len(outColumn) > 1:
                        columnNameCheck.append(outColumn[columnIndex][indexCol])
                    else:
                        if len(columnNameCheck) > 0 and columnNameCheck[indexCol] != '' and \
                                columnNameCheck[indexCol] != outColumn[columnIndex][indexCol]:
                            columnNameCheck[indexCol] = ''
                    if isinstance(pointGroup, list) and indexCol < len(pointGroup): chartPoint = pointGroup[indexCol]
                    if outColumn[columnIndex][indexCol].find('wordCloud') > 0: contentRow["type"] = "wordCloud"
                    detailValid = outDataProcess(outColumn[columnIndex][indexCol], indexCol, rowText, phrase,
                                                 json_data, detailValid, columnIndex, False, phraseData, chartPoint,
                                                 "", columnStringBack)
            else:
                if outColumn[columnIndex].find('wordCloud') > 0: contentRow["type"] = "wordCloud"
                if len(outColumn) > columnMax: columnMax = len(outColumn)
                detailValid = outDataProcess(outColumn[columnIndex], columnIndex, rowText, phrase, json_data,
                                             detailValid, -1, False, phraseData, chartPoint, "", columnStringBack)
    if contentRow["type"] == "wordchart":
        if len(columnNameCheck) > 2 and not all(columnNameCheckItem == '' for columnNameCheckItem in columnNameCheck):
            for indexColumn in range(2, len(columnNameCheck)):
                if columnNameCheck[indexColumn] != '':
                    columnNameStr = 'columnName' + str(indexColumn)
                    for detailItem in detailValid:
                        detailItem[columnNameStr] = '固定值'
        detailRemove, indexStar = [], 1
        if rowText != "": indexStar = 0
        for detailIndex, detailItem in enumerate(detailValid):
            removeFlag = True
            for indexColumn in range(indexStar, columnMax):
                if str(detailItem["columnName" + str(indexColumn)]).strip().find("固定值") > 1 and colEnd != '':
                    detailItem["columnName" + str(indexColumn)] = \
                        str(detailItem["columnName" + str(indexColumn)]).strip().replace('固定值', '')
                if detailItem["column" + str(indexColumn)] is not None and \
                        str(detailItem["column" + str(indexColumn)]).strip() != "" and \
                        not str(detailItem["columnName" + str(indexColumn)]).strip().find("固定值") > -1:
                    if is_number(sort_key(detailItem["column" + str(indexColumn)], None)) and \
                            float(str(sort_key(detailItem["column" + str(indexColumn)], None))) != 0.0:
                        removeFlag = False
                    if str(detailItem["column" + str(indexColumn)]).strip() == "空行":
                        removeFlag = False
                if zeroFill != "" and detailItem["column" + str(indexColumn)] is None:
                    detailValid[detailIndex]["column" + str(indexColumn)] = 0
            if removeFlag:
                removeFlag = False
                for indexColumn in range(indexStar, columnMax):
                    if not str(detailItem["columnName" + str(indexColumn)]).strip().find("固定值") > -1:
                        removeFlag = True
                        break
            if removeFlag:
                detailRemove.append(detailItem)
        for detailItem in detailRemove:
            detailValid.remove(detailItem)
        if "sort" in content.keys() and len(detailValid) > 0:
            detailValid = returnDataSort(detailValid, content["sort"], rowText)
        else:
            detailValid = returnDataSort(detailValid, None, rowText)
        for detailIndex, detailItem in enumerate(detailValid):
            if str(detailItem["column0"]).strip() == "空行":
                for indexColumn in range(0, columnMax):
                    detailItem["column" + str(indexColumn)] = ""
    if str(os.path.abspath(os.curdir)).find("core") > 0:
        filePath = os.path.abspath(os.curdir).replace("core", "pptx")
    else:
        filePath = os.path.join(os.path.abspath(os.curdir), "pptx")
    chartJsonString, chartJsonPath, fromtext = dict(discription=[], chartall=[]), "", \
                                               "[" + fromtext + position + "]"
    if position.find("图") > -1: fromtext = position
    chartJsonPath = os.path.join(filePath, 'charts', chartJson)
    if contentRow["type"] == "wordchart":
        if os.path.exists(chartJsonPath):
            with open(chartJsonPath, "r", encoding="utf-8") as f:
                chartJsonString = json.load(f)
                f.close()
    if len(detailValid) > 0:
        if contentRow["type"] == "wordchart":
            rowStardef = lambda: "" if "rowStar" not in content.keys() else content["rowStar"]
            colStardef = lambda: "" if "colStar" not in content.keys() else content["colStar"]
            tableResizedef = lambda: "" if "tableResize" not in content.keys() else content["tableResize"]
            colTitledef = lambda: "" if "colTitle" not in content.keys() else content["colTitle"]
            parameterdef = lambda: "" if "parameter" not in content.keys() else content["parameter"]
            chartHeightdef = lambda: "" if "chartHeight" not in content.keys() else content["chartHeight"]
            chartfiledef = lambda: "" if "chartfile" not in content.keys() else content["chartfile"]
            dataLabelColdef = lambda: "" if "dataLabelCol" not in content.keys() else content["dataLabelCol"]
            tableColdef = lambda: "" if "tableCol" not in content.keys() else content["tableCol"]
            colordef = lambda: "" if "color" not in content.keys() else content["color"]
            colorColdef = lambda: "" if "colorCol" not in content.keys() else content["colorCol"]
            rowStar, parameter, chartHeight, dataLabelCol, tableCol, color, colorCol, chartfile = \
                rowStardef(), parameterdef(), chartHeightdef(), dataLabelColdef(), tableColdef(), \
                colordef(), colorColdef(), chartfiledef()
            datasource, datasourceFirst, datasourceLast, datahead, wordChartJson, colStar, tableResize, colTitle = \
                [], [], [], [""], {}, colStardef(), tableResizedef(), colTitledef()
            if len(sortLast) > 0:
                datasourceLast = sortLast
                datasourceLast.reverse()
            if len(sortFirst) > 0:
                datasourceFirst = sortFirst
                datasourceFirst.reverse()
            if isinstance(title, str):
                if title == "":
                    if rowText != "":
                        dataColumnMax = columnMax
                    else:
                        dataColumnMax = columnMax - 1
                    for indexRow in range(dataColumnMax):
                        datahead.append(" ")
                elif title != "delete":
                    datahead.append(title)
            else:
                if isinstance(title, list):
                    if title[0].strip() == "":
                        datahead = []
                    for titleIndex in range(len(title)):
                        datahead.append(title[titleIndex])
            if allReplace is not None:
                for datasourceIndex, datasourceItem in enumerate(datahead):
                    if isinstance(allReplace, list):
                        replaceFrom = allReplace[0]
                        replaceTo = allReplace[1]
                        for replaceIndex, replaceItem in enumerate(replaceFrom):
                            if datasourceItem.strip() == str(replaceItem).strip() and replaceIndex < len(replaceTo):
                                if replaceTo[replaceIndex] is None:
                                    datahead[datasourceIndex] = ""
                                else:
                                    datahead[datasourceIndex] = replaceTo[replaceIndex]
            if len(datahead) > 1: datasource.append(datahead)
            sumdata, sumName = [], []
            if displayRow != "" and len(detailValid) > int(displayRow) + 1:
                displayRowCount = 0
                for detailIndex in range(int(displayRow) - 2, -1, -1):
                    displayRowFlag = True
                    for indexRow in range(0, columnMax):
                        if detailValid[detailIndex]["column" + str(indexRow)] != \
                                detailValid[int(displayRow) - 1]["column" + str(indexRow)]:
                            displayRowFlag = False
                            break
                    if displayRowFlag:
                        if displayRowCount == 0: displayRowCount = 1
                        displayRowCount += 1
                    else:
                        if displayRowCount == 0:
                            displayRowFlag = True
                            for indexRow in range(0, columnMax):
                                if detailValid[int(displayRow)]["column" + str(indexRow)] != \
                                        detailValid[int(displayRow) - 1]["column" + str(indexRow)]:
                                    displayRowFlag = False
                            if displayRowFlag: displayRowCount = 1
                        break
                if 1 >= int(displayRow) - displayRowCount and int(displayRow) > 1:
                    displayRowCount = 0
                    for detailIndex in range(int(displayRow), len(detailValid)):
                        displayRowFlag = True
                        for indexRow in range(0, columnMax):
                            if detailValid[detailIndex]["column" + str(indexRow)] != \
                                    detailValid[int(displayRow) - 1]["column" + str(indexRow)]:
                                displayRowFlag = False
                                break
                        if displayRowFlag:
                            displayRowCount -= 1
                        else:
                            break
                if displayRowCount != 0: displayRow = str(int(displayRow) - displayRowCount)
                for indexRow in range(0, columnMax):
                    sumdata.append(0)
                    sumName.append("")
            textRow, indexStar, indexAdd, columnSplit = "text", 0, 1, False
            if rowText == "":
                textRow, indexStar, indexAdd = "column0", 1, 0
                if isinstance(title, list) and len(title) > columnMax: columnSplit = True
            else:
                if isinstance(title, list) and len(title) - 1 > columnMax: columnSplit = True
            for detailIndex, detailItem in enumerate(detailValid):
                dataFlag2 = False
                if displayRow != "" and detailIndex >= int(displayRow) and len(detailValid) > int(displayRow) + 1:
                    if displayText == "":
                        if len(datasource) - len(datasourceLast) < int(displayRow):
                            datadetail = [outputFormatData(detailItem[textRow],
                                                           detailItem[textRow.replace("column", "columnName")],
                                                           point, 0, unitsBefore, unitsAfter, replaceText, 0)]
                            for indexColumn in range(indexStar, columnMax):
                                datadetail.append(outputFormatData(detailItem["column" + str(indexColumn)],
                                                                   detailItem["columnName" + str(indexColumn)],
                                                                   point, indexColumn + indexAdd, unitsBefore,
                                                                   unitsAfter, replaceText, 0))
                            datasource.append(datadetail)
                            if len(datasourceLast) > 0:
                                for datasourceLastIndex in range(len(datasourceLast)):
                                    del datasourceLast[datasourceLastIndex]
                        else:
                            break
                    else:
                        datadetail = [displayText]
                else:
                    datadetail = [outputFormatData(detailItem[textRow],
                                                   detailItem[textRow.replace("column", "columnName")], point, 0,
                                                   unitsBefore, unitsAfter, replaceText, 0)]
                if displayRow != "" and detailIndex >= int(displayRow) and len(detailValid) > int(displayRow) + 1:
                    for indexColumn in range(indexStar, columnMax):
                        if detailItem["columnName" + str(indexColumn)] == "固定值":
                            sumdata[indexColumn] = detailItem["column" + str(indexColumn)]
                        else:
                            sumdata[indexColumn] += detailItem["column" + str(indexColumn)]
                        sumName[indexColumn] = detailItem["columnName" + str(indexColumn)]
                else:
                    for indexColumn in range(indexStar, columnMax):
                        datadetail.append(outputFormatData(detailItem["column" + str(indexColumn)],
                                                           detailItem["columnName" + str(indexColumn)], point,
                                                           indexColumn + indexAdd, unitsBefore,
                                                           unitsAfter, replaceText, 0))
                if displayRow != "" and detailIndex >= int(displayRow) and len(detailValid) > int(displayRow) + 1:
                    if detailIndex == len(detailValid) - 1 and displayText != "":
                        for indexColumn in range(indexStar, columnMax):
                            if not columnSplit:
                                datadetail.append(outputFormatData(str(sumdata[indexColumn]), sumName[indexColumn],
                                                                   point, indexColumn + indexAdd, unitsBefore,
                                                                   unitsAfter,
                                                                   replaceText, 0))
                            else:
                                blankFlag = False
                                for titleIndex in range(columnMax, len(title)):
                                    if str(title[titleIndex]).strip() == str(detailItem[textRow]).strip():
                                        blankFlag = True
                                if blankFlag:
                                    datadetail.append("")
                                    for titleIndex in range(columnMax, len(title)):
                                        if str(title[titleIndex]).strip() == str(detailItem[textRow]).strip():
                                            datadetail.append(outputFormatData(str(sumdata[indexColumn]),
                                                                               sumName[indexColumn], point,
                                                                               indexColumn + indexAdd, unitsBefore,
                                                                               unitsAfter, replaceText, 0))
                                        else:
                                            datadetail.append("")
                                else:
                                    datadetail.append(outputFormatData(str(sumdata[indexColumn]),
                                                                       sumName[indexColumn], point,
                                                                       indexColumn + indexAdd, unitsBefore,
                                                                       unitsAfter, replaceText, 0))
                                    for titleIndex in range(columnMax, len(title)):
                                        datadetail.append("")
                        datasource.append(datadetail)
                else:
                    if detailItem[textRow] in sortFirst:
                        for sortFirstIndex, sortFirstItem in enumerate(datasourceFirst):
                            if isinstance(sortFirstItem, str) and detailItem[textRow] == sortFirstItem:
                                datasourceFirst[sortFirstIndex] = datadetail
                                dataFlag2 = True
                                break
                    if detailItem[textRow] in sortLast:
                        for sortLastIndex, sortLastItem in enumerate(datasourceLast):
                            if isinstance(sortLastItem, str) and detailItem[textRow] == sortLastItem:
                                datasourceLast[sortLastIndex] = datadetail
                                dataFlag2 = True
                                break
                    if not dataFlag2:
                        datasource.append(datadetail)
            for itemLast in datasourceLast:
                if isinstance(itemLast, list): datasource.append(itemLast)
            for itemFirst in datasourceFirst:
                if len(datahead) > 1:
                    if isinstance(itemFirst, list): datasource.insert(1, itemFirst)
                else:
                    if isinstance(itemFirst, list): datasource.insert(0, itemFirst)
            chartfilePath, chartJsonPath, chartHeightValue, chartfileValue, deleteCol = "", "", "", "", []
            if isinstance(chartHeight, list):
                if len(datasource) > int(chartHeight[1]):
                    chartHeightValue = chartHeight[2]
                else:
                    chartHeightValue = chartHeight[0]
            if len(datasource) > 1 and len(datasource[0]) > 2 and len(datasource[0]) == len(datasource[1]) and \
                    title != "delete" and colEnd == '':
                for colIndex in range(1, len(datasource[0])):
                    dataFlag = True
                    for rowIndex, rowItem in enumerate(datasource):
                        if rowIndex > 0 and not (str(rowItem[colIndex]).strip() == "" or
                                                 (str(rowItem[colIndex]).find('%') > -1 and
                                                  float(str(rowItem[colIndex]).replace('%', '')) == 0.0)):
                            dataFlag = False
                            break
                    if dataFlag: deleteCol.append(colIndex)
                if len(deleteCol) > 0: datasource = np.delete(datasource, deleteCol, axis=1).tolist()
            if colEnd == '' and len(datasource) > 1 and len(datasource[0]) > 1:
                colEnd = chr(ord('@') + len(datasource[0]))
            if isinstance(chartfile, list):
                if len(datasource) > int(chartfile[1]):
                    chartfileValue = os.path.join(filePath, 'charts', chartfile[2])
                    fromtextDel = chartfile[0]
                    fromtext = chartfile[2]
                else:
                    chartfileValue = os.path.join(filePath, 'charts', chartfile[0])
                    if chartfile[0] == "chart-bys-bar1.docx":
                        if len(datasource[0]) >= 4: datasource = np.delete(datasource, [1, 3], axis=1).tolist()
                    fromtextDel = chartfile[2]
                chartJsonString["chartall"].append(dict(fromtext=fromtextDel, chartHeight="", dataFlag="false",
                                                        chartfile="", datasource="", rowStar="",
                                                        colStar="", tableResize="", colTitle="",
                                                        parameter="", dataLabelCol="", tableCol="",
                                                        color="", colorCol="", chartLabelCol=chartLabelCol,
                                                        colEnd=""))
                if not Path(chartfileValue).is_file():
                    chartfileValue = ""
            if colTitle == "delete":
                datasource = np.delete(datasource, [0], axis=1).tolist()
                colTitle = ""
            chartJsonString["chartall"].append(
                dict(fromtext=fromtext, chartHeight=chartHeightValue, dataFlag="true",
                     chartfile=chartfileValue, datasource=datasource, rowStar=rowStar,
                     colStar=colStar, tableResize=tableResize, colTitle=colTitle,
                     parameter=parameter, dataLabelCol=dataLabelCol, tableCol=tableCol,
                     color=color, colorCol=colorCol, chartLabelCol=chartLabelCol,
                     colEnd=colEnd, point=point))
        elif contentRow["type"] == "wordCloud":
            fileName = fromtext + MyGuid() + '.png'
            picName = os.path.join(filePath, 'charts', fileName)
            imageMask, imageColors = None, None
            if edition is not None:
                imagePath = os.path.join(filePath, 'template', templateId + edition)
                if os.path.exists(imagePath + '.png'):
                    try:
                        imageMask = np.array(Image.open(imagePath + '.png'))
                        imageColors = ImageColorGenerator(imageMask)
                    except Exception as e:
                        pass
            font_path = os.path.join(os.path.abspath(os.curdir), 'simhei.ttf')
            if imageMask is None:
                wc = WordCloud(font_path=font_path, background_color='white', width=550, prefer_horizontal=1,
                               height=300).generate_from_frequencies(detailValid)
            else:
                wc = WordCloud(font_path=font_path, background_color='white', width=350, mask=imageMask,
                               height=250, prefer_horizontal=1). \
                    generate_from_frequencies(detailValid)
            wc.to_file(picName)
            for slide in documentPptx.slides:
                text_shapes, chart_shapes, table_shapes = [], [], []
                for shape in slide.shapes:
                    iter_shape(shape, text_shapes, chart_shapes, table_shapes)
                for shape in text_shapes:
                    if str(shape.text).find(fromtext) > -1:
                        shape.text = ''
                        slide.shapes.add_picture(picName, shape.left, shape.top, width=Cm(14.5), height=Cm(8))
                        os.remove(picName)
                        break
    else:
        if contentRow["type"] == "wordchart":
            deleteChart(documentPptx, fromtext, slideDelete)
            chartJsonString["chartall"].append(dict(fromtext=fromtext, chartHeight="", dataFlag="false",
                                                    chartfile="", datasource="", rowStar="",
                                                    colStar="", tableResize="", colTitle="",
                                                    parameter="", dataLabelCol="", tableCol="",
                                                    color="", colorCol="", chartLabelCol=chartLabelCol,colEnd=""))
    if contentRow["type"] == "wordchart":
        chartJsonPath = os.path.join(filePath, 'charts', chartJson)
        with open(chartJsonPath, "w", encoding="utf-8") as fp:
            fp.write(json.dumps(chartJsonString, indent=4))
            fp.close()
    return None


def deleteChart(documentPptx, fromtext, slideDelete):
    try:
        if slideDelete is not None:
            for slideDeleteItem in slideDelete:
                if fromtext in slideDeleteItem['chart_shapes_title']:
                    slideDeleteItem['chart_shapes_title'].remove(fromtext)
                    break

        chart_change = False
        for slide in documentPptx.slides:
            text_shapes, chart_shapes, table_shapes = [], [], []
            for shape in slide.shapes:
                iter_shape(shape, text_shapes, chart_shapes, table_shapes)
            for shape in chart_shapes:
                if shape.chart.has_title and shape.chart.chart_title.text_frame.text.find(fromtext) > -1:
                    chart = shape.element
                    chart.getparent().remove(chart)
                    chart_change = True
                    break
            if chart_change:break
    except Exception as e:
        pass


def outDataProcess(outColumn, index, rowText, phrase, json_data, detailValid, rowIndex, discriptionFlag,
                   phraseData, point, rowPhrase, columnStringBack):
    if rowText == "textRow":
        optionId, optionText = "valueColumn", "textColumn"
    elif rowText == "textColumn":
        optionId, optionText = "valueRow", "textRow"
    else:
        optionId, optionText = "value", "text"
    columnString, textString, optionTextString, detailValidText, columnName, outValueName = \
        "column" + str(index), "", "", "text", "columnName" + str(index), "outValueText"
    detailValidPhrase, detailValidTextPhrase, textColumnTop, detailValidTextPhraseFlag = "", "", "", True
    if isinstance(rowPhrase, list):
        if len(rowPhrase) > rowIndex  > -1:
            if rowPhrase[rowIndex].find('data') > -1 and rowPhrase[rowIndex].find(':') > -1:
                phraseText = ''
                if rowPhrase[rowIndex].find('textRow') > -1 and rowPhrase[rowIndex].find('textColumn') > -1:
                    detailValidTextPhraseFlag = False
            else:
                phraseText = rowPhrase[rowIndex]
        else:
            phraseText = ""
    else:
        phraseText = ""
    if isinstance(outColumn, str) and str(outColumn).find("{}") > -1:
        outColumn, detailValidIndexStart = outColumn.split(';'), 0
        if isinstance(phrase, str) and str(phrase).strip() == "":
            detailValidIndexStart = len(detailValid) - 1
        for detailValidIndex in range(detailValidIndexStart, len(detailValid)):
            detailValidItem = detailValid[detailValidIndex]
            calculation, conversionValue, conversionFinal, optionOutValue, outValueFlag = \
                myCalculation(), [], "", "", False
            if 'optionOutValue' in detailValidItem.keys(): optionOutValue = detailValidItem["optionOutValue"]
            if phraseText != "" and "phrase" in detailValidItem.keys():detailValidPhrase = detailValidItem["phrase"]
            if "phrase" in detailValidItem.keys() and detailValidTextPhraseFlag:
                detailValidTextPhrase = detailValidItem["phrase"]
            for outColumnIndex, outColumnItem in enumerate(outColumn):
                if outColumnIndex > 0:
                    if outColumnItem.find(":") >= 0:
                        headFlag, dataValue, detailValidFlag,textString = False, None, False, ""
                        outData = outColumnItem.split(':')
                        datasource = json.loads(json_data[outData[0].strip()])
                        head, detailValidFrom = datasource["head"][0], datasource["detailValid"]
                        if head["analysis"] == "means" or outColumnItem.find('Chi_Square_') >= 0 or \
                                outColumnItem.find('pearson_') >= 0 or outColumnItem.find('spearman_') >= 0 or \
                                outColumnItem.find('variance_') >= 0 or outColumnItem.find('F_T_') >= 0:
                            headFlag = True
                        if (head["analysis"] == "comparemeans" or head["analysis"] == "crosstabs" or
                            head["analysis"] == "crosstabsMultiple" or head["analysis"] == "crosstabsSort") and \
                                rowText == "text":
                            rowText = "textRow"
                        if check_json_format(json.dumps(phrase)) and not isinstance(phrase, str):
                            if outData[0].strip() in phrase.keys() and phrase[outData[0].strip()] != '值标签':
                                textString = phrase[outData[0].strip()]
                        if outData[1].find("=") >= 0:
                            outValue = outData[1].strip().split('=')
                            if outValue[0].strip() == 'count' and '/' in outColumn:
                                outValueName = 'validpercent'
                            else:
                                outValueName = outValue[0].strip()
                            if discriptionFlag and columnString not in columnStringBack.keys():
                                if outValue[0].strip() == 'text' or outValue[0].strip() == 'value':
                                    columnStringBack[columnString] = \
                                        "option" + outValue[0].strip() + \
                                        returnColumnIndex(columnStringBack, "option" + outValue[0].strip())
                                else:
                                    columnStringBack[columnString] = \
                                        outValueName + returnColumnIndex(columnStringBack, outValueName)
                        else:
                            outValue = outData[1].strip()
                            if outValue.strip() == 'count' and '/' in outColumn:
                                outValueName = 'validpercent'
                            else:
                                outValueName = outValue.strip()
                            if discriptionFlag and columnString not in columnStringBack.keys():
                                if outValue.strip() == 'text' or outValue.strip() == 'value':
                                    columnStringBack[columnString] = "option" + outValue.strip() + \
                                                                     returnColumnIndex(columnStringBack,
                                                                                       "option" + outValue.strip())
                                else:
                                    columnStringBack[columnString] = outValueName + \
                                                                     returnColumnIndex(columnStringBack, outValueName)
                        if isinstance(outValue, list):
                            if outValue[1].find('data') > -1 and outValue[1].find('top') > -1:
                                datasourceValue = json.loads(json_data[outValue[1].strip().
                                                             replace('topValue', '').replace('topText', '')])
                                detailValidValue = datasourceValue["detailValid"]
                                detailValidValue.sort(key=lambda x: x["validpercent"], reverse=True)
                                if outValue[1].find('topValue') > -1:
                                    outValue[1] = str(detailValidValue[0]['value'])
                                else:
                                    outValue[1] = str(detailValidValue[0]['text'])
                                textColumnTop = detailValidValue[0]['text']
                            optionValue = outValue[1].split('&')
                            for optionValueIndex, optionValueItem in enumerate(optionValue):
                                if is_number(optionValueItem) and str(optionValueItem).find(".0") > 0 and \
                                        float(optionValueItem) - math.floor(float(optionValueItem)) == 0:
                                    optionValue[optionValueIndex] = str(math.floor(float(optionValueItem)))
                            if (rowText == "" and textString == "") or (textString != "" and
                               (detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString or
                                detailValidTextPhrase == textString)):
                                detailValidFlag = True
                            for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                if head["analysis"] == "frequency" or head["analysis"] == "multiple":
                                    optionId, optionText = "value", "text"
                                elif head["analysis"] == "comparemeans" and rowText.strip() == "":
                                    optionId, optionText = "valueRow", "textRow"
                                else:
                                    if rowText.strip() == '':
                                        textString = ''
                                        if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" \
                                                or head["analysis"] == "crosstabsSort":
                                            optionId, optionText = "valueColumn", "textColumn"
                                    else:
                                        if isinstance(detailValidFromItem[rowText], list):
                                            textString = ""
                                            for textItem in detailValidFromItem[rowText]:
                                                textString += str(textItem)
                                        else:
                                            textString = str(detailValidFromItem[rowText])
                                if (rowText == "" and textString == "") or \
                                        detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString \
                                        or detailValidTextPhrase == textString:
                                    detailValidFlag = True
                                    if isinstance(detailValidFromItem[optionText], list):
                                        optionTextString = ""
                                        for textItem in detailValidFromItem[optionText]:
                                            optionTextString += str(textItem)
                                    else:
                                        optionTextString = str(detailValidFromItem[optionText])
                                    for optionValueItem in optionValue:
                                        if str(optionValueItem).strip() == str(int(detailValidFromItem[optionId])) or \
                                                str(optionValueItem).strip() == optionTextString:
                                            dataValueAdd, outValueFlag = \
                                                outputData(detailValidFromItem, outValue[0].strip(), point)
                                            dataValue = sumDataReturn(dataValue, dataValueAdd)
                        else:
                            if (rowText == "" and textString == "") or (textString != "" and
                               (detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString or
                                detailValidTextPhrase == textString)):
                                detailValidFlag = True
                            if headFlag:
                                if outValue.find('text') >= 0:
                                    dataValue = head[outValue]
                                    detailValidFlag = True
                                else:
                                    dataValue, outValueFlag = outputData(head, outValue.strip(), point)
                                    if len(detailValid) == 1 or (phraseText == "" and textString == ""):
                                        detailValidFlag = True
                            else:
                                for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                    if rowText != "":
                                        if isinstance(detailValidFromItem[rowText], list):
                                            textString = ""
                                            for textItem in detailValidFromItem[rowText]:
                                                textString += str(textItem)
                                        else:
                                            textString = str(detailValidFromItem[rowText])
                                        if detailValidTextPhrase != '' and (head["analysis"] == "crosstabs" or
                                                                            head["analysis"] == "crosstabsMultiple" or
                                                                            head["analysis"] == "crosstabsSort"):
                                            if isinstance(detailValidFromItem['textColumn'], list):
                                                textColumn = ""
                                                for textItem in detailValidFromItem['textColumn']:
                                                    textColumn += str(textItem)
                                            else:
                                                textColumn = str(detailValidFromItem['textColumn'])
                                            if detailValidTextPhrase + detailValidItem[detailValidText] == \
                                                    textString + textColumn:
                                                detailValidFlag = True
                                                dataValueAdd, outValueFlag = \
                                                    outputData(detailValidFromItem, outValue.strip(), point)
                                                dataValue = sumDataReturn(dataValue, dataValueAdd)
                                        else:
                                            if detailValidPhrase+detailValidItem[detailValidText] == \
                                                    phraseText+textString or detailValidTextPhrase == textString:
                                                detailValidFlag = True
                                                dataValueAdd, outValueFlag = \
                                                    outputData(detailValidFromItem, outValue.strip(), point)
                                                dataValue = sumDataReturn(dataValue, dataValueAdd)
                                    else:
                                        dataValueAdd, outValueFlag = outputData(detailValidFromItem, outValue.strip(),
                                                                                point)
                                        dataValue = sumDataReturn(dataValue, dataValueAdd)
                        if detailValidFlag:
                            conversionValue.append(str(dataValue))
                    else:
                        conversionValue.append(outColumnItem)
            if len(conversionValue) > 0 and len(conversionValue) == len(outColumn) - 1:
                conversionFinal = calculation.main(outColumn[0].format(*conversionValue))
                if conversionFinal != '':
                    if not discriptionFlag and outValueFlag: conversionFinal = float(conversionFinal) * 100
                    detailValid[detailValidIndex][columnString], outValueFlag = \
                        outputData(float(conversionFinal), "", point)
                else:
                    if columnString not in detailValid[detailValidIndex].keys():
                        detailValid[detailValidIndex][columnString] = None
                if columnString in columnStringBack.keys():
                    detailValid[detailValidIndex][columnStringBack[columnString]] = \
                        detailValid[detailValidIndex][columnString]
            else:
                if columnString not in detailValid[detailValidIndex].keys():
                    detailValid[detailValidIndex][columnString] = None
                if discriptionFlag and columnString in columnStringBack.keys():
                    if columnStringBack[columnString] not in detailValid[detailValidIndex].keys():
                        detailValid[detailValidIndex][columnStringBack[columnString]] = None
            detailValid[detailValidIndex][columnName] = outValueName
            detailValid[detailValidIndex]["rowIndex"] = rowIndex
            if textColumnTop != "":detailValid[detailValidIndex]['textColumn'] = textColumnTop
    elif str(outColumn).find(":") >= 0 and str(outColumn).find("data") >= 0:
        outData, datasource = outColumn.split(':'), []
        if outData[0].strip().find(',') > 0:
            for outDataItem in outData[0].strip().split(','):
                if "fieldText" in detailValid[0].keys() and detailValid[0]["fieldText"] is not None:
                    datasource.append(json.loads(json_data[outDataItem.strip()]))
                else:
                    datasource = json.loads(json_data[outDataItem.strip()])
                    break
        else:
            datasource = json.loads(json_data[outData[0].strip()])
        if str(phraseData).strip() == str(outData[0].strip()).strip():detailValidText = "phrase"
        dataValueString, dataFlag = "", False
        if outData[1].find("=") >= 0:
            outValue = outData[1].strip().split('=')
            if outValue[1].strip().find('data') > -1 and outValue[1].strip().find('max') > -1:
                maxStr = outValue[1].strip()[-1]
                if maxStr != 'x' and is_number(maxStr):
                    maxNumber = int(maxStr) - 1
                    datasourcePerMax = json.loads(json_data[outValue[1].strip().replace('max' + maxStr, '')])
                else:
                    maxNumber = 0
                    datasourcePerMax = json.loads(json_data[outValue[1].strip().replace('max', '')])
                detailValidPerMax = datasourcePerMax["detailValid"]
                sort_column = 'validpercent'
                if len(detailValidPerMax) > 0 and 'casepercent' in detailValidPerMax[0].keys():
                    sort_column = 'casepercent'
                detailValidPerMax.sort(key=lambda x: sort_key(x[sort_column], True), reverse=True)
                if "varValues" in datasourcePerMax["head"][0].keys() and \
                        str(datasourcePerMax["head"][0]["varValues"]).strip() == '':
                    outValue[1] = detailValidPerMax[maxNumber]['text']
                else:
                    outValue[1] = str(detailValidPerMax[maxNumber]['value'])
            if discriptionFlag and columnString not in columnStringBack.keys():
                if outValue[0].strip() == 'text' or outValue[0].strip() == 'value':
                    if outValue[1].strip() == "max" and outValue[0].strip() == 'text':
                        columnStringBack[columnString] = \
                            outValue[0].strip() + "max" + \
                            returnColumnIndex(columnStringBack, outValue[0].strip() + 'max')
                    else:
                        columnStringBack[columnString] = \
                            "option" + outValue[0].strip() + \
                            returnColumnIndex(columnStringBack, "option" + outValue[0].strip())
                else:
                    columnStringBack[columnString] = \
                        outValue[0].strip() + returnColumnIndex(columnStringBack, outValue[0].strip())
        else:
            outValue = outData[1].strip()
            if discriptionFlag and columnString not in columnStringBack.keys():
                if outValue.strip() == 'text' or outValue.strip() == 'value':
                    columnStringBack[columnString] = "option" + outValue.strip() + \
                                                     returnColumnIndex(columnStringBack,
                                                                       "option" + outValue.strip())
                else:
                    columnStringBack[columnString] = outValue.strip() + \
                                                     returnColumnIndex(columnStringBack, outValue.strip())
        if isinstance(datasource, dict):
            head = datasource["head"][0]
            if head["analysis"] == "frequency" or head["analysis"] == "multiple":
                optionId, optionText = "value", "text"
            elif head["analysis"] == "comparemeans":
                optionId, optionText = "valueRow", "textRow"
            elif head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                    head["analysis"] == "crosstabsSort":
                optionId, optionText = "valueColumn", "textColumn"
            if (head["analysis"] == "comparemeans" or head["analysis"] == "crosstabs" or
                head["analysis"] == "crosstabsMultiple" or head["analysis"] == "crosstabsSort") and rowText == "text":
                rowText = "textRow"
            if 'noCondition' in head.keys() and str(head['noCondition']).strip() != '':
                outValueNameAfter = '固定值'
            else:
                outValueNameAfter = ''
            if isinstance(outValue, list):
                if outValue[0].strip() == 'percentileRank': outValueNameAfter = '固定值'
                outValueName = outValue[0].strip() + outValueNameAfter
                if outValue[1].find('data') > -1 and outValue[1].find('top') > -1:
                    datasourceValue = json.loads(json_data[outValue[1].strip().
                                                 replace('topValue', '').replace('topText', '')])
                    detailValidValue = datasourceValue["detailValid"]
                    sort_column = 'validpercent'
                    if len(detailValidValue) > 0 and 'casepercent' in detailValidValue[0].keys():
                        sort_column = 'casepercent'
                    detailValidValue.sort(key=lambda x: x[sort_column], reverse=True)
                    if outValue[1].find('topValue') > -1:
                        outValue[1] = str(detailValidValue[0]['value'])
                    else:
                        outValue[1] = str(detailValidValue[0]['text'])
                    textColumnTop = detailValidValue[0]['text']
                optionValue, detailValidFrom = outValue[1].split('&'), datasource["detailValid"]
                sort_column = 'validpercent'
                if len(detailValidFrom) > 0 and 'casepercent' in detailValidFrom[0].keys(): sort_column = 'casepercent'
                for optionValueIndex, optionValueItem in enumerate(optionValue):
                    if is_number(optionValueItem) and str(optionValueItem).find(".0") > 0 and \
                        float(optionValueItem) - math.floor(float(optionValueItem)) == 0:
                        optionValue[optionValueIndex] = str(math.floor(float(optionValueItem)))
                if outValue[1].strip() == "max":
                    optionValue = "max"
                if outValue[1].strip().find('sort') > -1 and outValue[1].strip().find('sortValue') < 0 and \
                        outValue[1].strip().find('sortText') < 0:
                    optionId = "sort"
                    for optionValueIndex, optionValueItem in enumerate(optionValue):
                        optionValue[optionValueIndex] = int(optionValueItem.replace('sort', ''))
                if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                        head["analysis"] == "crosstabsSort":
                    if rowText != "":
                        if rowText == "text" or rowText == "textRow":
                            if optionId != 'sort': optionId = "valueColumn"
                            optionText = "textColumn"
                        for detailValidIndex, detailValidItem in enumerate(detailValid):
                            if phraseText != "" and "phrase" in detailValidItem.keys():
                                detailValidPhrase = detailValidItem["phrase"]
                            if "phrase" in detailValidItem.keys() and detailValidTextPhraseFlag:
                                detailValidTextPhrase = detailValidItem["phrase"]
                            dataValue, dataValueMax, dataFlag, outValueFlag, dataValueString = None, 0.0, False, False, ''
                            for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                if isinstance(detailValidFromItem[rowText], list):
                                    textString = ""
                                    for textItem in detailValidFromItem[rowText]:
                                        textString += str(textItem)
                                else:
                                    textString = str(detailValidFromItem[rowText])
                                if isinstance(detailValidFromItem[optionText], list):
                                    optionTextString = ""
                                    for textItem in detailValidFromItem[optionText]:
                                        optionTextString += str(textItem)
                                else:
                                    optionTextString = str(detailValidFromItem[optionText])
                                if detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString or \
                                        detailValidTextPhrase == textString:
                                    if isinstance(optionValue, str) and optionValue == "max":
                                        if detailValidFromItem[sort_column] > dataValueMax:
                                            dataValueMax = detailValidFromItem[sort_column]
                                            if str(outValue[0].strip()).find("text") >= 0:
                                                dataValueString = optionTextString
                                            else:
                                                dataValue, outValueFlag = outputData(detailValidFromItem,
                                                                                     outValue[0].strip(), point)
                                    else:
                                        for optionValueItem in optionValue:
                                            if str(optionValueItem).strip() == str(int(detailValidFromItem[optionId])) or \
                                                    str(optionValueItem).strip() == optionTextString:
                                                dataFlag = True
                                                if str(outValue[0].strip()).find("text") >= 0:
                                                    if rowText.strip() == str(outValue[0].strip()).strip():
                                                        dataValueString = textString
                                                    else:
                                                        if dataValueString != '' and optionId == "sort":
                                                            dataValueString += '、'
                                                        dataValueString = dataValueString + optionTextString
                                                else:
                                                    dataValueAdd, outValueFlag = outputData(detailValidFromItem,
                                                                                            outValue[0].strip(), point)
                                                    dataValue = sumDataReturn(dataValue, dataValueAdd)
                            if dataValueString != "":
                                detailValid[detailValidIndex][columnString] = dataValueString
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    detailValid[detailValidIndex][columnStringBack[columnString]] = dataValueString
                            else:
                                if dataFlag:
                                    if not discriptionFlag and outValueFlag and dataValue is not None:
                                        dataValue = dataValue * 100
                                    detailValid[detailValidIndex][columnString] = dataValue
                                    if discriptionFlag and columnString in columnStringBack.keys()\
                                            :detailValid[detailValidIndex][columnStringBack[columnString]] = dataValue
                                else:
                                    if columnString not in detailValid[detailValidIndex].keys():
                                        detailValid[detailValidIndex][columnString] = None
                                    if discriptionFlag and columnString in columnStringBack.keys():
                                        if columnStringBack[columnString] not in detailValid[detailValidIndex].keys():
                                            detailValid[detailValidIndex][columnStringBack[columnString]] = None
                            detailValid[detailValidIndex]["rowIndex"] = rowIndex
                            detailValid[detailValidIndex][columnName] = outValueName
                            if textColumnTop != "": detailValid[detailValidIndex]['textColumn'] = textColumnTop
                    else:
                        dataValue, dataValueMax, outValueFlag = None, 0.0, False
                        for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                            if isinstance(detailValidFromItem["textColumn"], list):
                                textString = ""
                                for textItem in detailValidFromItem["textColumn"]:
                                    textString += str(textItem)
                            else:
                                textString = str(detailValidFromItem["textColumn"])
                            if isinstance(optionValue, str) and optionValue == "max":
                                if detailValidFromItem[sort_column] > dataValueMax:
                                    dataValueMax = detailValidFromItem[sort_column]
                                    if str(outValue[0].strip()).find("text") >= 0:
                                        dataValueString = textString
                                    else:
                                        dataValue, outValueFlag = outputData(detailValidFromItem, outValue[0].strip(),
                                                                             point)
                            else:
                                for optionValueItem in optionValue:
                                    if str(optionValueItem).strip() == str(int(detailValidFromItem["valueColumn"])) or \
                                            str(optionValueItem).strip() == textString:
                                        dataFlag = True
                                        if str(outValue[0].strip()).find("text") >= 0:
                                            if isinstance(detailValidFromItem[outValue[0].strip()], list):
                                                optionTextString = ""
                                                for textItem in detailValidFromItem[outValue[0].strip()]:
                                                    optionTextString += str(textItem)
                                            else:
                                                optionTextString = str(detailValidFromItem[outValue[0].strip()])
                                            dataValueString = dataValueString + optionTextString
                                        else:
                                            dataValueAdd, outValueFlag = outputData(detailValidFromItem,
                                                                                    outValue[0].strip(), point)
                                            dataValue = sumDataReturn(dataValue, dataValueAdd)
                        if dataValueString != "":
                            detailValid[len(detailValid) - 1][columnString] = dataValueString
                            if discriptionFlag and columnString in columnStringBack.keys():
                                detailValid[len(detailValid) - 1][columnStringBack[columnString]] = dataValueString
                        else:
                            if dataFlag:
                                if not discriptionFlag and outValueFlag and dataValue is not None:
                                    dataValue = dataValue * 100
                                detailValid[len(detailValid) - 1][columnString] = dataValue
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    detailValid[len(detailValid) - 1][columnStringBack[columnString]] = dataValue
                            else:
                                if columnString not in detailValid[len(detailValid) - 1].keys():
                                    detailValid[len(detailValid) - 1][columnString] = None
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    if columnStringBack[columnString] not in detailValid[len(detailValid) - 1].keys():
                                        detailValid[len(detailValid) - 1][columnStringBack[columnString]] = None
                        detailValid[len(detailValid) - 1]["rowIndex"] = rowIndex
                        detailValid[len(detailValid) - 1][columnName] = outValueName
                        if textColumnTop != "": detailValid[len(detailValid) - 1]['textColumn'] = textColumnTop
                else:
                    if rowText != "":
                        for detailValidIndex, detailValidItem in enumerate(detailValid):
                            dataValue, dataValueMax, optionOutValue, outValueFlag, dataFlag = None, 0.0, '', False, False
                            if 'optionOutValue' in detailValidItem.keys():
                                optionOutValue = detailValidItem["optionOutValue"]
                            if phraseText != "" and "phrase" in detailValidItem.keys():
                                detailValidPhrase = detailValidItem["phrase"]
                            if "phrase" in detailValidItem.keys() and detailValidTextPhraseFlag:
                                detailValidTextPhrase = detailValidItem["phrase"]
                            for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                if isinstance(detailValidFromItem[optionText], list):
                                    textString = ""
                                    for textItem in detailValidFromItem[optionText]:
                                        textString += str(textItem)
                                else:
                                    textString = str(detailValidFromItem[optionText])
                                valueString =  str(detailValidFromItem[optionId])
                                if rowText == "textRow":
                                    if optionOutValue != '':
                                        if detailValidPhrase + optionOutValue == phraseText + valueString or \
                                                detailValidPhrase + optionOutValue == phraseText + textString:
                                            if str(outValue[0].strip()).find("text") >= 0:
                                                if isinstance(detailValidFromItem[outValue[0].strip()], list):
                                                    optionTextString = ""
                                                    for textItem in detailValidFromItem[outValue[0].strip()]:
                                                        optionTextString += str(textItem)
                                                else:
                                                    optionTextString = \
                                                        str(detailValidFromItem[outValue[0].strip()])
                                                dataValueString = dataValueString + optionTextString
                                            else:
                                                dataValueAdd, outValueFlag = \
                                                    outputData(detailValidFromItem, outValue[0].strip(), point)
                                                dataValue = sumDataReturn(dataValue, dataValueAdd)
                                            dataFlag = True
                                    else:
                                        if (detailValidPhrase + detailValidItem[detailValidText] ==
                                            phraseText + phrase[outData[0].strip()] or
                                            detailValidTextPhrase == phrase[outData[0].strip()]) and \
                                                phrase[outData[0].strip()] != '值标签':
                                            if isinstance(optionValue, str) and optionValue == "max":
                                                if detailValidFromItem[sort_column] > dataValueMax:
                                                    dataValueMax = detailValidFromItem[sort_column]
                                                    if str(outValue[0].strip()).find("text") >= 0:
                                                        dataValueString = textString
                                                    else:
                                                        dataValue, outValueFlag = \
                                                            outputData(detailValidFromItem, outValue[0].strip(), point)
                                            else:
                                                for optionValueItem in optionValue:
                                                    if str(optionValueItem).strip() == \
                                                            str(int(detailValidFromItem[optionId])) or \
                                                            str(optionValueItem).strip() == textString:
                                                        if str(outValue[0].strip()).find("text") >= 0:
                                                            if isinstance(detailValidFromItem[outValue[0].strip()],
                                                                          list):
                                                                optionTextString = ""
                                                                for textItem in detailValidFromItem[
                                                                    outValue[0].strip()]:
                                                                    optionTextString += str(textItem)
                                                            else:
                                                                optionTextString = \
                                                                    str(detailValidFromItem[outValue[0].strip()])
                                                            dataValueString = dataValueString + optionTextString
                                                        else:
                                                            dataValueAdd, outValueFlag = \
                                                                outputData(detailValidFromItem, outValue[0].strip(),
                                                                           point)
                                                            dataValue = sumDataReturn(dataValue, dataValueAdd)
                                            dataFlag = True
                                else:
                                    if optionOutValue != '':
                                        if detailValidPhrase + optionOutValue == phraseText + valueString or \
                                            detailValidPhrase + optionOutValue == phraseText + textString:
                                            dataValueAdd, outValueFlag = \
                                                outputData(detailValidFromItem, outValue[0].strip(), point)
                                            dataValue = sumDataReturn(dataValue, dataValueAdd)
                                            dataFlag = True
                                    else:
                                        if detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString:
                                            dataValueAdd, outValueFlag = \
                                                outputData(detailValidFromItem, outValue[0].strip(), point)
                                            dataValue = sumDataReturn(dataValue, dataValueAdd)
                                            dataFlag = True
                            if dataFlag:
                                if dataValueString != "":
                                    detailValid[detailValidIndex][columnString] = dataValueString
                                    if discriptionFlag and columnString in columnStringBack.keys():
                                        detailValid[detailValidIndex][columnStringBack[columnString]] = dataValueString
                                else:
                                    if not discriptionFlag and outValueFlag and dataValue is not None:
                                        dataValue = dataValue * 100
                                    detailValid[detailValidIndex][columnString] = dataValue
                                    if discriptionFlag and columnString in columnStringBack.keys():
                                        detailValid[detailValidIndex][columnStringBack[columnString]] = dataValue
                            else:
                                if columnString not in detailValid[detailValidIndex].keys():
                                    detailValid[detailValidIndex][columnString] = None
                                if discriptionFlag and columnString in columnStringBack.keys() and \
                                        columnStringBack[columnString] not in detailValid[detailValidIndex].keys():
                                    detailValid[detailValidIndex][columnStringBack[columnString]] = None
                            detailValid[detailValidIndex]["rowIndex"] = rowIndex
                            detailValid[detailValidIndex][columnName] = outValueName
                            if textColumnTop != "": detailValid[detailValidIndex]['textColumn'] = textColumnTop
                    else:
                        dataValue, dataValueMax, outValueFlag = None, 0.0, False
                        if head["analysis"] == "comparemeans":
                            if len(outValue) > 1 and outValue[1].find('data') > -1 and outValue[1].find('sort') > -1:
                                datasourceOut = json.loads(json_data[str(outValue[1]).replace('sortValue', '').
                                                           replace('sortText', '')])
                                if outValue[1].find('sortValue') > -1:
                                    outValueText = str(datasourceOut["detailValid"][0]['value']).strip()
                                else:
                                    outValueText = str(datasourceOut["detailValid"][0]['text']).strip()
                                detailValidFrom.sort(key=lambda x: x["average"], reverse=True)
                                for detailValidIndex, detailValidItem in enumerate(detailValidFrom):
                                    if 'textRow' in detailValidItem.keys():
                                        detailValidItemText = str(detailValidItem["textRow"]).strip()
                                        detailValidItemValue = str(detailValidItem["valueRow"]).strip()
                                    else:
                                        detailValidItemText = str(detailValidItem["text"]).strip()
                                        detailValidItemValue = str(detailValidItem["value"]).strip()
                                    if outValueText == detailValidItemText or outValueText == detailValidItemValue:
                                        dataValue = sumDataReturn(detailValidIndex, 1)
                                        dataFlag = True
                                        break
                            else:
                                for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                    if isinstance(detailValidFromItem[optionText], list):
                                        textString = ""
                                        for textItem in detailValidFromItem[optionText]:
                                            textString += str(textItem)
                                    else:
                                        textString = str(detailValidFromItem[optionText])
                                    if isinstance(optionValue, str) and optionValue == "max":
                                        if dataValue is None or detailValidFromItem["average"] > dataValue:
                                            dataValue = detailValidFromItem["average"]
                                    else:
                                        for optionValueItem in optionValue:
                                            if str(optionValueItem).strip() == str(int(detailValidFromItem["valueRow"])) or\
                                                    str(optionValueItem).strip() == textString:
                                                dataFlag = True
                                                dataValueAdd, outValueFlag = outputData(detailValidFromItem,
                                                                                        outValue[0].strip(), point)
                                                dataValue = sumDataReturn(dataValue, dataValueAdd)
                        else:
                            dataValueStringGroup = []
                            for optionIndex in range(len(optionValue)):
                                dataValueStringGroup.append("")
                            for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                if isinstance(detailValidFromItem[optionText], list):
                                    textString = ""
                                    for textItem in detailValidFromItem[optionText]:
                                        textString += str(textItem)
                                else:
                                    textString = str(detailValidFromItem[optionText])
                                if isinstance(optionValue, str) and optionValue == "max":
                                    if detailValidFromItem[sort_column] > dataValueMax:
                                        dataFlag = True
                                        dataValueMax = detailValidFromItem[sort_column]
                                        if str(outValue[0].strip()).find("text") >= 0:
                                            dataValueString = textString
                                        else:
                                            dataValue, outValueFlag = outputData(detailValidFromItem,
                                                                                 outValue[0].strip(), point)
                                else:
                                    for optionValueIndex, optionValueItem in enumerate(optionValue):
                                        if str(optionValueItem).strip() == str(int(detailValidFromItem[optionId])) or \
                                                str(optionValueItem).strip() == textString:
                                            dataFlag = True
                                            if str(outValue[0].strip()).find("text") >= 0:
                                                if isinstance(detailValidFromItem[outValue[0].strip()], list):
                                                    optionTextString = ""
                                                    for textItem in detailValidFromItem[outValue[0].strip()]:
                                                        optionTextString += str(textItem)
                                                else:
                                                    optionTextString = str(detailValidFromItem[outValue[0].strip()])
                                                dataValueStringGroup[optionValueIndex] = optionTextString
                                            else:
                                                dataValueAdd, outValueFlag = outputData(detailValidFromItem,
                                                                                        outValue[0].strip(), point)
                                                dataValue = sumDataReturn(dataValue, dataValueAdd)
                            for dataValueStringGroupItem in dataValueStringGroup:
                                dataValueString += dataValueStringGroupItem
                        if dataValueString != "":
                            detailValid[len(detailValid) - 1][columnString] = dataValueString
                            if discriptionFlag and columnString in columnStringBack.keys():
                                detailValid[len(detailValid) - 1][columnStringBack[columnString]] = dataValueString
                        else:
                            if dataFlag:
                                if not discriptionFlag and outValueFlag and dataValue is not None:
                                    dataValue = dataValue * 100
                                detailValid[len(detailValid) - 1][columnString] = dataValue
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    detailValid[len(detailValid) - 1][columnStringBack[columnString]] = dataValue
                            else:
                                if columnString not in detailValid[len(detailValid) - 1].keys():
                                    detailValid[len(detailValid) - 1][columnString] = None
                                if discriptionFlag and columnString in columnStringBack.keys() and \
                                        columnStringBack[columnString] not in detailValid[len(detailValid) - 1].keys():
                                    detailValid[len(detailValid) - 1][columnStringBack[columnString]] = None
                        detailValid[len(detailValid) - 1]["rowIndex"] = rowIndex
                        detailValid[len(detailValid) - 1][columnName] = outValueName
                        if textColumnTop != "": detailValid[len(detailValid) - 1]['textColumn'] = textColumnTop
            else:
                if outValue == 'percentileRank': outValueNameAfter = '固定值'
                outValueName = outValue + outValueNameAfter
                if head["analysis"] == "means" or outValue.find('Chi_Square_') >= 0 or outValue.find('pearson_') >= 0 or \
                        outValue.find('spearman_') >= 0 or outValue.find('variance_') >= 0 or outValue.find('F_T_') >= 0:
                    if rowText != "":
                        for detailValidIndex, detailValidItem in enumerate(detailValid):
                            if phraseText != "" and "phrase" in detailValidItem.keys():
                                detailValidPhrase = detailValidItem["phrase"]
                            if "phrase" in detailValidItem.keys()and detailValidTextPhraseFlag:
                                detailValidTextPhrase = detailValidItem["phrase"]
                            dataValue, dataFlag, outValueFlag = None, False, False
                            if (isinstance(phrase, str) and phrase == "") or outValue not in head.keys():
                                detailValidFrom = datasource["detailValid"]
                                for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                    if isinstance(detailValidFromItem["text"], list):
                                        textString = ""
                                        for textItem in detailValidFromItem["text"]:
                                            textString += str(textItem)
                                    else:
                                        textString = str(detailValidFromItem["text"])
                                    if detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString or \
                                            detailValidTextPhrase == textString:
                                        dataFlag = True
                                        dataValue, outValueFlag = outputData(detailValidFromItem, outValue, point)
                                        break
                            else:
                                for keyPhrase, valuePhrase in phrase.items():
                                    if ((detailValidPhrase + detailValidItem[detailValidText] ==
                                         phraseText + valuePhrase or detailValidTextPhrase == valuePhrase) and
                                         outData[0] == keyPhrase) or (valuePhrase == '值标签' and outData[0] == keyPhrase):
                                        dataFlag = True
                                        if outValue.find('text') >= 0:
                                            dataValue = head[outValue]
                                        else:
                                            dataValue, outValueFlag = outputData(head, outValue, point)
                            if dataFlag:
                                if not discriptionFlag and outValueFlag and dataValue is not None:
                                    dataValue = dataValue * 100
                                detailValid[detailValidIndex][columnString] = dataValue
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    detailValid[detailValidIndex][columnStringBack[columnString]] = dataValue
                            else:
                                if columnString not in detailValid[detailValidIndex].keys():
                                    detailValid[detailValidIndex][columnString] = None
                                if discriptionFlag and columnString in columnStringBack.keys() and \
                                        columnStringBack[columnString] not in detailValid[detailValidIndex].keys():
                                    detailValid[detailValidIndex][columnStringBack[columnString]] = None
                            detailValid[detailValidIndex]["rowIndex"] = rowIndex
                            detailValid[detailValidIndex][columnName] = outValueName
                            if textColumnTop != "": detailValid[detailValidIndex]['textColumn'] = textColumnTop
                    else:
                        if outValue.find('text') >= 0:
                            dataValue = head[outValue]
                            outValueFlag = False
                        else:
                            dataValue, outValueFlag = outputData(head, outValue, point)
                        if not discriptionFlag and outValueFlag and dataValue is not None:
                            dataValue = dataValue * 100
                        detailValid[len(detailValid) - 1][columnString] = dataValue
                        if discriptionFlag and columnString in columnStringBack.keys():
                            detailValid[len(detailValid) - 1][columnStringBack[columnString]] = dataValue
                        detailValid[len(detailValid) - 1]["rowIndex"] = rowIndex
                        detailValid[len(detailValid) - 1][columnName] = outValueName
                        if textColumnTop != "": detailValid[len(detailValid) - 1]['textColumn'] = textColumnTop
                elif head["analysis"] == "wordcloud" and outValue == 'wordCloud':
                    detailValid = head['wordCloud']
                else:
                    detailValidFrom = datasource["detailValid"]
                    if rowText != "":
                        for detailValidIndex, detailValidItem in enumerate(detailValid):
                            if phraseText != "" and "phrase" in detailValidItem.keys():
                                detailValidPhrase = detailValidItem["phrase"]
                            if "phrase" in detailValidItem.keys() and detailValidTextPhraseFlag:
                                detailValidTextPhrase = detailValidItem["phrase"]
                            dataValue, dataFlag, outValueFlag = None, False, False
                            for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                if head["analysis"] == "comparemeans":
                                    if isinstance(detailValidFromItem[optionText], list):
                                        textString = ""
                                        for textItem in detailValidFromItem[optionText]:
                                            textString += str(textItem)
                                    else:
                                        textString = str(detailValidFromItem[optionText])
                                    if detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString or\
                                            detailValidTextPhrase == textString:
                                        dataFlag = True
                                        if str(outValue.strip()).find("text") >= 0:
                                            dataValue = str(detailValidFromItem[outValue]).strip()
                                        else:
                                            dataValueAdd, outValueFlag = outputData(detailValidFromItem, outValue,
                                                                                    point)
                                            dataValue = sumDataReturn(dataValue, dataValueAdd)
                                elif head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                                        head["analysis"] == "crosstabsSort":
                                    if isinstance(detailValidFromItem[rowText], list):
                                        textString = ""
                                        for textItem in detailValidFromItem[rowText]:
                                            textString += str(textItem)
                                    else:
                                        textString = str(detailValidFromItem[rowText])
                                    if detailValidTextPhrase != '':
                                        if isinstance(detailValidFromItem[optionText], list):
                                            textColumn = ""
                                            for textItem in detailValidFromItem[optionText]:
                                                textColumn += str(textItem)
                                        else:
                                            textColumn = str(detailValidFromItem[optionText])
                                        if detailValidTextPhrase + detailValidItem[detailValidText] == \
                                                textString + textColumn:
                                            dataFlag = True
                                            if str(outValue.strip()).find("text") >= 0:
                                                dataValue = str(detailValidFromItem[outValue]).strip()
                                            else:
                                                dataValueAdd, outValueFlag = outputData(detailValidFromItem, outValue,
                                                                                        point)
                                                dataValue = sumDataReturn(dataValue, dataValueAdd)
                                    else:
                                        if detailValidPhrase + detailValidItem[detailValidText] == \
                                                phraseText + textString:
                                            dataFlag = True
                                            if str(outValue.strip()).find("text") >= 0:
                                                dataValue = str(detailValidFromItem[outValue]).strip()
                                            else:
                                                dataValueAdd, outValueFlag = outputData(detailValidFromItem, outValue,
                                                                                        point)
                                                dataValue = sumDataReturn(dataValue, dataValueAdd)
                                else:
                                    if isinstance(detailValidFromItem[optionText], list):
                                        textString = ""
                                        for textItem in detailValidFromItem[optionText]:
                                            textString += str(textItem)
                                    else:
                                        textString = str(detailValidFromItem[optionText])
                                    if detailValidPhrase + detailValidItem[detailValidText] == phraseText + textString or\
                                            detailValidTextPhrase == textString or \
                                        (isinstance(phrase, dict) and phrase[outData[0].strip()] != '值标签' and
                                         detailValidItem[detailValidText] == phrase[outData[0].strip()]):
                                        dataFlag = True
                                        if str(outValue.strip()).find("text") >= 0:
                                            dataValue = str(detailValidFromItem[outValue]).strip()
                                        else:
                                            dataValueAdd, outValueFlag = outputData(detailValidFromItem, outValue,
                                                                                    point)
                                            dataValue = sumDataReturn(dataValue, dataValueAdd)
                            if dataFlag:
                                if not discriptionFlag and outValueFlag and dataValue is not None:
                                    dataValue = dataValue * 100
                                detailValid[detailValidIndex][columnString] = dataValue
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    detailValid[detailValidIndex][columnStringBack[columnString]] = dataValue
                            else:
                                if columnString not in detailValid[detailValidIndex].keys():
                                    detailValid[detailValidIndex][columnString] = None
                                if discriptionFlag and columnString in columnStringBack.keys() and \
                                        columnStringBack[columnString] not in detailValid[detailValidIndex].keys():
                                    detailValid[detailValidIndex][columnStringBack[columnString]] = None
                            detailValid[detailValidIndex]["rowIndex"] = rowIndex
                            detailValid[detailValidIndex][columnName] = outValueName
                            if textColumnTop != "": detailValid[detailValidIndex]['textColumn'] = textColumnTop
                    else:
                        dataValue, outValueFlag = None, False
                        for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                            dataFlag = True
                            if str(outValue).find("text") >= 0:
                                if isinstance(detailValidFromItem[outValue], list):
                                    textString = ""
                                    for textItem in detailValidFromItem[outValue]:
                                        textString += str(textItem)
                                else:
                                    textString = str(detailValidFromItem[outValue])
                                dataValueString = dataValueString + textString
                            else:
                                dataValue, outValueFlag = outputData(detailValidFromItem, outValue, point)
                        if dataValueString != "":
                            detailValid[len(detailValid) - 1][columnString] = dataValueString
                            if discriptionFlag and columnString in columnStringBack.keys():
                                detailValid[len(detailValid) - 1][columnStringBack[columnString]] = dataValueString
                        else:
                            if dataFlag:
                                if not discriptionFlag and outValueFlag and dataValue is not None:
                                    dataValue = dataValue * 100
                                detailValid[len(detailValid) - 1][columnString] = dataValue
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    detailValid[len(detailValid) - 1][columnStringBack[columnString]] = dataValue
                            else:
                                if columnString not in detailValid[len(detailValid) - 1].keys():
                                    detailValid[len(detailValid) - 1][columnString] = None
                                if discriptionFlag and columnString in columnStringBack.keys() and\
                                        columnStringBack[columnString] not in detailValid[len(detailValid) - 1].keys():
                                    detailValid[len(detailValid) - 1][columnStringBack[columnString]] = None
                        detailValid[len(detailValid) - 1]["rowIndex"] = rowIndex
                        detailValid[len(detailValid) - 1][columnName] = outValueName
                        if textColumnTop != "": detailValid[len(detailValid) - 1]['textColumn'] = textColumnTop
        else:
            for detailValidIndex, detailValidItem in enumerate(detailValid):
                for datasourceItem in datasource:
                    head = datasourceItem["head"][0]
                    if head["analysis"] == "frequency" or head["analysis"] == "multiple":
                        optionId, optionText = "value", "text"
                    elif head["analysis"] == "comparemeans":
                        optionId, optionText = "valueRow", "textRow"
                    elif head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                            head["analysis"] == "crosstabsSort":
                        optionId, optionText = "valueColumn", "textColumn"
                    if (head["analysis"] == "comparemeans" or head["analysis"] == "crosstabs" or
                        head["analysis"] == "crosstabsMultiple"or head["analysis"] == "crosstabsSort") \
                            and rowText == "text":
                        rowText = "textRow"
                    if 'variableID' in head.keys() and \
                            str(detailValidItem['fieldText']).strip() == str(head['variableID']).strip():
                        if 'noCondition' in head.keys() and str(head['noCondition']).strip() != '':
                            outValueNameAfter = '固定值'
                        else:
                            outValueNameAfter = ''
                        if isinstance(outValue, list):
                            if outValue[0].strip() == 'percentileRank': outValueNameAfter = '固定值'
                            outValueName = outValue[0].strip() + outValueNameAfter
                        else:
                            if outValue == 'percentileRank': outValueNameAfter = '固定值'
                            outValueName = outValue + outValueNameAfter
                        if head["analysis"] == "means":
                            dataValue, outValueFlag = outputData(head, outValue, point)
                            if not discriptionFlag and outValueFlag and dataValue is not None:
                                dataValue = dataValue * 100
                            detailValid[detailValidIndex][columnString] = dataValue
                            if discriptionFlag and columnString in columnStringBack.keys():
                                detailValid[detailValidIndex][columnStringBack[columnString]] = dataValue
                            detailValid[detailValidIndex]["rowIndex"] = rowIndex
                            detailValid[detailValidIndex][columnName] = outValueName
                        else:
                            detailValidFrom = datasourceItem["detailValid"]
                            dataValue, outValueFlag, dataValueMax = None, False, 0
                            if isinstance(outValue, list):
                                optionValue = outValue[1].split('&')
                                for optionValueIndex, optionValueItem in enumerate(optionValue):
                                    if is_number(optionValueItem) and str(optionValueItem).find(".0") > 0 and \
                                        float(optionValueItem) - math.floor(float(optionValueItem)) == 0:
                                        optionValue[optionValueIndex] = str(math.floor(float(optionValueItem)))
                                if outValue[1].strip() == "max":
                                    optionValue = "max"
                                if outValue[1].strip().find('sort') > -1 and outValue[1].strip().find('sortValue') < 0 \
                                        and outValue[1].strip().find('sortText') < 0:
                                    optionId = "sort"
                                    for optionValueIndex, optionValueItem in enumerate(optionValue):
                                        optionValue[optionValueIndex] = int(optionValueItem.replace('sort', ''))
                                dataValueStringGroup = []
                                for optionIndex in range(len(optionValue)):
                                    dataValueStringGroup.append("")
                                for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                    if isinstance(detailValidFromItem[optionText], list):
                                        textString = ""
                                        for textItem in detailValidFromItem[optionText]:
                                            textString += str(textItem)
                                    else:
                                        textString = str(detailValidFromItem[optionText])
                                    if isinstance(optionValue, str) and optionValue == "max":
                                        if detailValidFromItem["count"] > dataValueMax:
                                            dataValueMax = detailValidFromItem["count"]
                                            if str(outValue[0].strip()).find("text") >= 0:
                                                dataValueString = textString
                                            else:
                                                dataValue, outValueFlag = outputData(detailValidFromItem,
                                                                                     outValue[0].strip(), point)
                                    else:
                                        for optionValueIndex, optionValueItem in enumerate(optionValue):
                                            if str(optionValueItem).strip() == str(int(detailValidFromItem[optionId])) or \
                                                    str(optionValueItem).strip() == textString:
                                                dataFlag = True
                                                if str(outValue[0].strip()).find("text") >= 0:
                                                    if isinstance(detailValidFromItem[outValue[0].strip()], list):
                                                        optionTextString = ""
                                                        for textItem in detailValidFromItem[outValue[0].strip()]:
                                                            optionTextString += str(textItem)
                                                    else:
                                                        optionTextString = str(detailValidFromItem[outValue[0].strip()])
                                                    dataValueStringGroup[optionValueIndex] = optionTextString
                                                else:
                                                    dataValueAdd, outValueFlag = outputData(detailValidFromItem,
                                                                                            outValue[0].strip(), point)
                                                    dataValue = sumDataReturn(dataValue, dataValueAdd)
                                for dataValueStringGroupItem in dataValueStringGroup:
                                    dataValueString += dataValueStringGroupItem
                            else:
                                for detailValidFromIndex, detailValidFromItem in enumerate(detailValidFrom):
                                    dataFlag = True
                                    if str(outValue).find("text") >= 0:
                                        if isinstance(detailValidFromItem[outValue], list):
                                            textString = ""
                                            for textItem in detailValidFromItem[outValue]:
                                                textString += str(textItem)
                                        else:
                                            textString = str(detailValidFromItem[outValue])
                                        dataValueString = dataValueString + textString
                                    else:
                                        dataValue, outValueFlag = outputData(detailValidFromItem, outValue, point)
                            if dataValueString != "":
                                detailValid[detailValidIndex][columnString] = dataValueString
                                if discriptionFlag and columnString in columnStringBack.keys():
                                    detailValid[detailValidIndex][columnStringBack[columnString]] = dataValueString
                            else:
                                if dataFlag:
                                    if not discriptionFlag and outValueFlag and dataValue is not None:
                                        dataValue = dataValue * 100
                                    detailValid[detailValidIndex][columnString] = dataValue
                                    if discriptionFlag and columnString in columnStringBack.keys():
                                        detailValid[detailValidIndex][columnStringBack[columnString]] = dataValue
                                else:
                                    if columnString not in detailValid[detailValidIndex].keys():
                                        detailValid[detailValidIndex][columnString] = None
                                    if discriptionFlag and columnString in columnStringBack.keys() and \
                                            columnStringBack[columnString] not in detailValid[detailValidIndex].keys():
                                        detailValid[detailValidIndex][columnStringBack[columnString]] = None
                            detailValid[detailValidIndex]["rowIndex"] = rowIndex
                            detailValid[detailValidIndex][columnName] = outValueName
                        break
    else:
        if outColumn.find("data") >= 0 and outColumn.find("/") >= 0:
            if outColumn.find(",") >= 0:
                detailValid[len(detailValid) - 1][columnString] = passRate(outColumn, json_data)
                detailValid[len(detailValid) - 1]["rowIndex"] = rowIndex
                detailValid[len(detailValid) - 1][columnName] = "validpercent"
        else:
            outValueName = '固定值'
            if rowText != "":
                for detailValidIndex, detailValidItem in enumerate(detailValid):
                    setFlag = True
                    if index > 0:
                        setFlag = False
                        for cnt in range(index):
                            if "column" + str(cnt) in detailValid[detailValidIndex]:
                                if detailValid[detailValidIndex]["column" + str(cnt)] is not None:
                                    setFlag = True
                            else:
                                setFlag = True
                    if columnString not in detailValid[detailValidIndex] or \
                        detailValid[detailValidIndex][columnString] is None:
                        if setFlag:
                            detailValid[detailValidIndex][columnString] = outColumn
                        else:
                            detailValid[detailValidIndex][columnString] = None
                    detailValid[detailValidIndex]["rowIndex"] = rowIndex
                    if columnName not in detailValid[detailValidIndex].keys() or \
                            str(detailValid[detailValidIndex][columnName]).strip() == "":
                        detailValid[detailValidIndex][columnName] = outValueName
            else:
                if discriptionFlag and "text" not in detailValid[len(detailValid) - 1].keys(): columnString = "text"
                setFlag = True
                if index > 1:
                    setFlag = False
                    for cnt in range(1,index):
                        if "column" + str(cnt) in detailValid[len(detailValid) - 1]:
                            if detailValid[len(detailValid) - 1]["column" + str(cnt)] is not None:
                                setFlag = True
                        else:
                            setFlag = True
                if setFlag:
                    detailValid[len(detailValid) - 1][columnString] = outColumn
                else:
                    if detailValid[len(detailValid) - 1]["column0"] == outColumn:
                        detailValid[len(detailValid) - 1]["column0"] = None
                        detailValid[len(detailValid) - 1][columnString] = outColumn
                    else:
                        detailValid[len(detailValid) - 1][columnString] = None
                detailValid[len(detailValid) - 1]["rowIndex"] = rowIndex
                if phraseText != '' and 'phrase' not in detailValid[len(detailValid) - 1].keys():
                    detailValid[len(detailValid) - 1]["phrase"] = phraseText
                if columnName not in detailValid[len(detailValid) - 1].keys() or \
                        str(detailValid[len(detailValid) - 1][columnName]).strip() == "":
                    detailValid[len(detailValid) - 1][columnName] = outValueName
    return detailValid


def rowDataProcess(outColumn, rowText, phrase, rowPhrase, rowNo, sortAll, json_data, discriptionFlag,phraseData, point,
                   sumColumn):
    phraseSave, dataSave, text, valueColumn, phraseBreak, columnMax, detailValid, detailValidTotal, textString, outData \
        = [], [], [], "", "", 0, [], [], "", []
    outDataSave, outColumnRowSave, detailValidTotalRowSave, outColumnRowSaveIndex, dataPhraseSave = [], [], [], 0, []
    if rowText == "textRow":
        valueColumn = "valueRow"
    elif rowText == "textColumn":
        valueColumn = "valueColumn"
    else:
        valueColumn = "value"
    rowPhraseDataFlag, sumColumnFlag, rowPhraseDataAllFlag = [], False, False
    if isinstance(rowPhrase, list):
        for rowPhraseItem in rowPhrase:
            if True == isinstance(rowPhraseItem, str) and rowPhraseItem.find("data") > -1 and \
                rowPhraseItem.find(":") > -1:
                rowPhraseDataFlag.append(True)
                rowPhraseDataAllFlag = True
            else:
                rowPhraseDataFlag.append(False)
    if True == isinstance(rowPhrase, str) and rowPhrase.find("data") > -1 and rowPhrase.find(":") > -1:
        rowPhraseDataFlag.append(True)
        rowPhrase = [rowPhrase]
        rowPhraseDataAllFlag = True
    if rowPhraseDataAllFlag:
        for rowPhraseIndex, rowPhraseItem in enumerate(rowPhrase):
            if rowPhraseDataFlag[rowPhraseIndex]:
                rowPhraseList = []
                if rowPhraseItem.find(";") > -1 :
                    rowOutDataAll = str(rowPhraseItem).split(';')
                    rowOutData, rowOutDataCount = rowOutDataAll[0].split(':'), len(rowOutDataAll)
                elif rowPhraseItem.find(":") > -1 :
                    rowOutDataAll, rowOutDataCount = None, 1
                    rowOutData = rowPhraseItem.split(':')
                else:
                    rowOutDataAll, rowOutDataCount, rowOutData = None, 1, ['','']
                outText, datasource = rowOutData[1].split(','), json.loads(json_data[rowOutData[0]])
                detailValidFrom, headPhrase, colPhrase, rowId, columnId, rowIndex, columnIndex = \
                    datasource["detailValid"], [], [], "", "", 0, 0
                for indexColumn in range(len(outColumn)):
                    if isinstance(outColumn[indexColumn], list):
                        if len(outColumn[indexColumn]) > columnMax: columnMax = len(outColumn[indexColumn])
                    else:
                        if len(outColumn) > columnMax: columnMax = len(outColumn)
                if len(outText) > 0:
                    for dataItem in detailValidFrom:
                        if isinstance(dataItem[outText[0]], list):
                            textString = ""
                            for textItem in dataItem[outText[0]]:
                                textString += str(textItem)
                        else:
                            textString = str(dataItem[outText[0]])
                        if textString not in rowPhraseList:rowPhraseList.append(textString)

                    for rowPhraseItemText in rowPhraseList:
                        colText = []
                        if len(outText) > 1:
                            for dataItem in detailValidFrom:
                                if isinstance(dataItem[outText[0]], list):
                                    textString = ""
                                    for textItem in dataItem[outText[0]]:
                                        textString += str(textItem)
                                else:
                                    textString = str(dataItem[outText[0]])
                                if rowPhraseItemText == textString:
                                    if isinstance(dataItem[outText[1]], list):
                                        textString = ""
                                        for textItem in dataItem[outText[1]]:
                                            textString += str(textItem)
                                    else:
                                        textString = str(dataItem[outText[1]])
                                    if textString not in colText: colText.append(textString)
                        else:
                            if sumColumn == "":
                                colText.append(rowPhraseItemText)
                            else:
                                colText.append(sumColumn)
                                sumColumnFlag = True
                        colPhrase.append(colText)
                if isinstance(rowOutDataAll, list):
                    headPhrase, rowPhraseList, colPhrase = copy.deepcopy(rowPhraseList), copy.deepcopy(colPhrase), []
                    rowOutData = rowOutDataAll[1].split(':')
                    outText, datasource = rowOutData[1].split(','), json.loads(json_data[rowOutData[0]])
                    detailValidFrom = datasource["detailValid"]
                    if len(outText) > 0:
                        for rowPhraseItemText in rowPhraseList:
                            colText = []
                            for rowPhraseColItem in rowPhraseItemText:
                                colItemText = []
                                if len(outText) > 1:
                                    for dataItem in detailValidFrom:
                                        if isinstance(dataItem[outText[0]], list):
                                            textString = ""
                                            for textItem in dataItem[outText[0]]:
                                                textString += str(textItem)
                                        else:
                                            textString = str(dataItem[outText[0]])
                                        if rowPhraseColItem == textString:
                                            if isinstance(dataItem[outText[1]], list):
                                                textString = ""
                                                for textItem in dataItem[outText[1]]:
                                                    textString += str(textItem)
                                            else:
                                                textString = str(dataItem[outText[1]])
                                            if textString not in colItemText: colItemText.append(textString)
                                else:
                                    if sumColumn == "":
                                        colItemText.append(rowPhraseItemText)
                                    else:
                                        colItemText.append(sumColumn)
                                        sumColumnFlag = True
                                colText.append(colItemText)
                            colPhrase.append(colText)
                phraseSave, indexPhrase = rowPhraseList, 0
                if len(headPhrase) > 0:
                    for headPhraseIndex, headPhraseItem in enumerate(headPhrase):
                        for rowPhraseListIndex, rowPhraseItemText in enumerate(rowPhraseList[headPhraseIndex]):
                            for colPhraseIndex, colPhraseItem in enumerate(colPhrase[headPhraseIndex][rowPhraseListIndex]):
                                colPhraseKey, colPhraseValue = None, None
                                if check_json_format(colPhraseItem):
                                    for colKey, colValue in json.loads(colPhraseItem.strip()).items():
                                        colPhraseKey, colPhraseValue = colKey, colValue
                                else:
                                    colPhraseKey = colPhraseItem
                                detailValid.append(dict(value=indexPhrase + 1, text=colPhraseValue,
                                                        phrase=rowPhraseItemText, headPhrase=headPhraseItem,
                                                        columnMax=columnMax, fieldText=colPhraseKey))
                                indexPhrase += 1
                else:
                    for rowPhraseListIndex, rowPhraseItemText in enumerate(rowPhraseList):
                        for colPhraseIndex, colPhraseItem in enumerate(colPhrase[rowPhraseListIndex]):
                            colPhraseKey, colPhraseValue = None, None
                            if check_json_format(colPhraseItem):
                                for colKey, colValue in json.loads(colPhraseItem.strip()).items():
                                    colPhraseKey, colPhraseValue = colKey, colValue
                            else:
                                colPhraseKey = colPhraseItem
                            detailValid.append(dict(value=indexPhrase + 1, text=colPhraseKey, phrase=rowPhraseItemText,
                                                    columnMax=columnMax, fieldText=colPhraseValue))
                            indexPhrase += 1
                detailValidTotal.append(copy.deepcopy(detailValid))
                detailValid.clear()
            else:
                if check_json_format(json.dumps(phrase)) and len(outColumn) > rowPhraseIndex and \
                        isinstance(outColumn[rowPhraseIndex], list):
                    for columnItem in outColumn[rowPhraseIndex]:
                        if columnItem.find(":") > -1:
                            outData = columnItem.split(':')
                            for key, value in phrase.items():
                                if str(outData[0]) == str(key):
                                    if str(value) not in text:
                                        if len(sortAll) == 0:
                                            if len(detailValid) > 0:
                                                rowNo = max(detailValidItem['value'] for detailValidItem in detailValid)
                                            rowNo += 1
                                        else:
                                            for sortIndex, sortItem in enumerate(sortAll):
                                                if str(value) == sortItem:
                                                    if rowNo > 0: rowNo -= sortIndex
                                                    else: rowNo += sortIndex
                                        text.append(str(value))
                                        detailValid.append(dict(value=rowNo, text=str(value),
                                                                phrase=rowPhrase[rowPhraseIndex], headPhrase="",
                                                                columnMax=columnMax))
                if len(detailValid) > 0:
                    detailValidTotal.append(copy.deepcopy(detailValid))
                    detailValid.clear()
    else:
        for index in range(len(outColumn)):
            if isinstance(outColumn[index], list):
                if len(outColumn[index]) > columnMax: columnMax = len(outColumn[index])
                for indexCol in range(len(outColumn[index])):
                    if outColumn[index][indexCol].find(":") >= 0:
                        if outColumn[index][indexCol].find("{}") > -1:
                            outColumnItem,outData = outColumn[index][indexCol].split(';'), ['']
                            for outColumnData in outColumnItem:
                                if outColumnData.find(":") >= 0:
                                    outData = outColumnData.split(':')
                                    break
                        else:
                            outData = outColumn[index][indexCol].split(':')
                        if isinstance(rowPhrase, list) and index < len(rowPhrase) and \
                                outData[0] + rowPhrase[index] not in dataPhraseSave:
                            dataSave.append(outData[0]), phraseSave.append(rowPhrase[index])
                            outDataSave.append(outData), outColumnRowSave.append(index)
                            dataPhraseSave.append(outData[0] + rowPhrase[index])
                        else:
                            if outData[0] not in dataSave:
                                dataSave.append(outData[0]), outDataSave.append(outData), outColumnRowSave.append(index)
            else:
                if len(outColumn) > columnMax: columnMax = len(outColumn)
                if outColumn[index].find(":") >= 0:
                    if outColumn[index].find("{}") > -1:
                        outColumnItem, outData = outColumn[index].split(';'), ['']
                        for outColumnData in outColumnItem:
                            if outColumnData.find(":") >= 0:
                                outData = outColumnData.split(':')
                                outData[0] = outData[0].replace('head', '')
                                break
                    else:
                        outData = outColumn[index].split(':')
                    if isinstance(rowPhrase, list) and index < len(rowPhrase) and \
                            outData[0] + rowPhrase[index] not in dataPhraseSave:
                        dataSave.append(outData[0]), phraseSave.append(rowPhrase[index])
                        outDataSave.append(outData), outColumnRowSave.append(index)
                        dataPhraseSave.append(outData[0] + rowPhrase[index])
                    else:
                        if outData[0] not in dataSave:
                            dataSave.append(outData[0]), outDataSave.append(outData), outColumnRowSave.append(index)
                            if isinstance(outColumn[0], str) and isinstance(rowPhrase, list):
                                phraseSave.append(rowPhrase[0])
        if len(phraseSave) > 0: phraseBreak = phraseSave[0]
        for dataSaveIndex, dataSaveItem in enumerate(dataSave):
            datasource = json.loads(json_data[dataSaveItem])
            head = datasource["head"][0]
            if head["analysis"] == "comparemeans" or head["analysis"] == "crosstabs" or \
                    head["analysis"] == "crosstabsMultiple"  or head["analysis"] == "crosstabsSort" \
                    or rowText == "textRow":
                rowText, valueColumn = "textRow", "valueRow"
            else:
                rowText, valueColumn = "text", "value"
            if rowText == "textRow":
                textRowFlag = True
                if check_json_format(json.dumps(phrase)):
                    if dataSaveItem in phrase.keys() and phrase[dataSaveItem] != '值标签':
                        textRowFlag = False
                if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                        head["analysis"] == "comparemeans"  or head["analysis"] == "crosstabsSort" and textRowFlag:
                    detailValidFrom = datasource["detailValid"]
                    for dataItem in detailValidFrom:
                        if isinstance(dataItem[rowText], list):
                            textString = ""
                            for textItem in dataItem[rowText]:
                                textString += str(textItem)
                        else:
                            textString = str(dataItem[rowText])
                        if textString not in text:
                            text.append(textString)
                            if len(phraseSave) > 0:
                                detailValid.append(dict(value=dataItem[valueColumn], text=textString, data=dataSaveItem,
                                                        phrase=phraseSave[dataSaveIndex], columnMax=columnMax))
                            else:
                                detailValid.append(dict(value=dataItem[valueColumn], text=textString,
                                                        data=dataSaveItem, columnMax=columnMax))
                else:
                    outData = outDataSave[dataSaveIndex]
                    optionOutValueSave = []
                    if check_json_format(json.dumps(phrase)):
                        for key, value in phrase.items():
                            if str(dataSaveItem) == str(key) or str(key).find(str(dataSaveItem) + 'No') >= 0:
                                if str(value) not in text and value != '值标签':
                                    if len(sortAll) == 0:
                                        if len(detailValid) > 0:
                                            rowNo = max(detailValidItem['value'] for detailValidItem in detailValid)
                                        rowNo += 1
                                    else:
                                        for sortIndex, sortItem in enumerate(sortAll):
                                            if str(value) == sortItem:
                                                if rowNo > 0:
                                                    rowNo -= sortIndex
                                                else:
                                                    rowNo += sortIndex
                                    text.append(str(value))
                                    optionOutValue = ''
                                    if head["analysis"] == "comparemeans" and len(outData) > 1 and \
                                            outData[1].find('=') > 0:
                                        if len(optionOutValueSave) == 0:
                                            outColumnCheck = outColumn[outColumnRowSave[dataSaveIndex]]
                                            for outColumnItem in outColumnCheck:
                                                if str(outColumnItem).find(dataSave[dataSaveIndex]) > -1 \
                                                        and str(outColumnItem).find('=') > 0:
                                                    optionOutValue = outColumnItem.split(':')[1].split('=')[1]
                                                    break
                                        else:
                                            for outColumnIndex in range(outColumnRowSave[dataSaveIndex],
                                                                        len(outColumn)):
                                                if str(outColumn[outColumnIndex]).find(dataSave[dataSaveIndex]) > -1:
                                                    outColumnCheck = outColumn[outColumnIndex]
                                                    for outColumnItem in outColumnCheck:
                                                        if str(outColumnItem).find(dataSave[dataSaveIndex]) > -1 \
                                                                and str(outColumnItem).find('=') > 0:
                                                            optionOutValue = outColumnItem.split(':')[1].split('=')[1]
                                                            if optionOutValue not in optionOutValueSave: break
                                                if optionOutValue != '' and optionOutValue not in optionOutValueSave: break
                                        optionOutValueSave.append(optionOutValue)
                                    if len(phraseSave) > 0:
                                        detailValid.append(dict(value=rowNo, text=str(value), data=dataSaveItem,
                                                                phrase=phraseSave[dataSaveIndex], columnMax=columnMax,
                                                                optionOutValue=optionOutValue))
                                    else:
                                        detailValid.append(dict(value=rowNo, text=str(value), data=dataSaveItem,
                                                                columnMax=columnMax, optionOutValue=optionOutValue))
            else:
                outData = outDataSave[dataSaveIndex]
                if head["analysis"] == "crosstabs" or head["analysis"] == "crosstabsMultiple" or \
                        head["analysis"] == "crosstabsSort":
                    if rowText == 'text': rowText, valueColumn = "textRow", "valueRow"
                    detailValidFrom = datasource["detailValid"]
                    for dataItem in detailValidFrom:
                        if isinstance(dataItem[rowText], list):
                            textString = ""
                            for textItem in dataItem[rowText]:
                                textString += str(textItem)
                        else:
                            textString = str(dataItem[rowText])
                        if textString not in text:
                            text.append(textString)
                            if len(phraseSave) > 0:
                                detailValid.append(
                                    dict(value=dataItem[valueColumn], text=textString, data=dataSaveItem,
                                         phrase=phraseSave[dataSaveIndex], columnMax=columnMax))
                            else:
                                detailValid.append(
                                    dict(value=dataItem[valueColumn], text=textString, data=dataSaveItem,
                                         columnMax=columnMax))
                elif (head["analysis"] == "means" and check_json_format(json.dumps(phrase)) and
                        (len(outData) <= 1 or (len(outData) > 1 and outData[1] != 'data'))) or \
                        (head["analysis"] == "frequency" and len(outData) > 1 and outData[1].find('=') > 0):
                    optionOutValueSave = []
                    for key, value in phrase.items():
                        if str(dataSaveItem) == str(key) or str(key).find(str(dataSaveItem) + 'No') >= 0:
                            if str(value) not in text:
                                text.append(str(value))
                                if len(sortAll) == 0:
                                    if len(detailValid) > 0:
                                        rowNo = max(detailValidItem['value'] for detailValidItem in detailValid)
                                    rowNo += 1
                                else:
                                    for sortIndex, sortItem in enumerate(sortAll):
                                        if str(key) == sortItem:
                                            if rowNo > 0: rowNo -= sortIndex
                                            else: rowNo += sortIndex
                                optionOutValue = ''
                                if head["analysis"] == "frequency" and len(outData) > 1 and outData[1].find('=') > 0:
                                    if len(optionOutValueSave) == 0:
                                        outColumnCheck = outColumn[outColumnRowSave[dataSaveIndex]]
                                        for outColumnItem in outColumnCheck:
                                            if str(outColumnItem).find(dataSave[dataSaveIndex]) > -1 \
                                                    and str(outColumnItem).find('=') > 0:
                                                optionOutValue = outColumnItem.split(':')[1].split('=')[1]
                                                break
                                    else:
                                        for outColumnIndex in range(outColumnRowSave[dataSaveIndex], len(outColumn)):
                                            if str(outColumn[outColumnIndex]).find(dataSave[dataSaveIndex]) > -1:
                                                outColumnCheck = outColumn[outColumnIndex]
                                                for outColumnItem in outColumnCheck:
                                                    if str(outColumnItem).find(dataSave[dataSaveIndex]) > -1 \
                                                            and str(outColumnItem).find('=') > 0:
                                                        optionOutValue = outColumnItem.split(':')[1].split('=')[1]
                                                        if optionOutValue not in optionOutValueSave: break
                                            if optionOutValue != '' and optionOutValue not in optionOutValueSave: break
                                    optionOutValueSave.append(optionOutValue)
                                if len(phraseSave) > 0:
                                    detailValid.append(dict(value=rowNo, text=str(value), data=dataSaveItem,
                                                            phrase=phraseSave[dataSaveIndex],columnMax=columnMax,
                                                            optionOutValue=optionOutValue))
                                else:
                                    detailValid.append(dict(value=rowNo, text=str(value), data=dataSaveItem,
                                                            columnMax=columnMax, optionOutValue=optionOutValue))
                else:
                    detailValidFrom = datasource["detailValid"]
                    if rowText == "textColumn" or rowText == "text":
                        for dataItem in detailValidFrom:
                            if isinstance(dataItem["text"], list):
                                textString = ""
                                for textItem in dataItem["text"]:
                                    textString += str(textItem)
                            else:
                                textString = str(dataItem["text"])
                            if textString not in text:
                                text.append(textString)
                                if len(phraseSave) > 0:
                                    detailValid.append(dict(value=dataItem["value"], text=textString, data=dataSaveItem,
                                                            phrase=phraseSave[dataSaveIndex], columnMax=columnMax))
                                else:
                                    detailValid.append(dict(value=dataItem["value"], text=textString,
                                                            data=dataSaveItem, columnMax=columnMax))
                    else:
                        for dataItem in detailValidFrom:
                            if isinstance(dataItem[rowText], list):
                                textString = ""
                                for textItem in dataItem[rowText]:
                                    textString += str(textItem)
                            else:
                                textString = str(dataItem[rowText])
                            if textString not in text:
                                text.append(textString)
                                if len(phraseSave) > 0:
                                    detailValid.append(
                                        dict(value=dataItem[valueColumn], text=textString, data=dataSaveItem,
                                             phrase=phraseSave[dataSaveIndex], columnMax=columnMax))
                                else:
                                    detailValid.append(
                                        dict(value=dataItem[valueColumn], text=textString, data=dataSaveItem,
                                             columnMax=columnMax))
            if len(phraseSave) > 0 and (dataSaveIndex == len(dataSave) - 1 or
                                        phraseBreak != phraseSave[dataSaveIndex + 1]):
                detailValidTotal.append(copy.deepcopy(detailValid))
                detailValidTotalRowSave.append(outColumnRowSave[outColumnRowSaveIndex])
                detailValid.clear(), text.clear()
                outColumnRowSaveIndex = dataSaveIndex + 1
            if len(phraseSave) > dataSaveIndex + 1: phraseBreak = phraseSave[dataSaveIndex + 1]
    columnStringBack = {}
    chartPoint = point
    if isinstance(point, dict) or isinstance(point, list): chartPoint = ''
    if len(phraseSave) > 0:
        for indexRow in range(len(outColumn)):
            if isinstance(point, list) and indexRow < len(point): chartPoint = point[indexRow]
            if isinstance(outColumn[indexRow], list):
                if len(detailValidTotalRowSave) > 0:
                    detailValidRowIndex = len(detailValidTotalRowSave) - 1
                    for detailValidTotalRowSaveIndex, detailValidTotalRowSaveItem in enumerate(detailValidTotalRowSave):
                        if indexRow >= detailValidTotalRowSaveItem:
                            detailValidRowIndex = detailValidTotalRowSaveIndex
                else:
                    detailValidRowIndex = copy.deepcopy(indexRow)
                detailValidTotalItem = detailValidTotal[detailValidRowIndex]
                if len(detailValidTotalItem) > 0:
                    for indexCol in range(len(outColumn[indexRow])):
                        if isinstance(point, list) and indexCol < len(point): chartPoint = point[indexCol]
                        detailValidTotal[detailValidRowIndex] = \
                            outDataProcess(outColumn[indexRow][indexCol], indexCol, rowText, phrase, json_data,
                                           detailValidTotalItem, indexRow, discriptionFlag, phraseData, chartPoint,
                                           rowPhrase, columnStringBack)
            else:
                detailValidTotal[0] = outDataProcess(outColumn[indexRow], indexRow, rowText, phrase, json_data,
                                                     detailValidTotal[0], -1, discriptionFlag, phraseData, chartPoint,
                                                     rowPhrase, columnStringBack)
    else:
        for indexRow in range(len(outColumn)):
            if isinstance(point, list) and indexRow < len(point): chartPoint = point[indexRow]
            if isinstance(outColumn[indexRow], list):
                for indexCol in range(len(outColumn[indexRow])):
                    if isinstance(point, list) and indexCol < len(point): chartPoint = point[indexCol]
                    detailValid = outDataProcess(outColumn[indexRow][indexCol], indexCol, rowText, phrase, json_data,
                                                 detailValid, indexRow, discriptionFlag, phraseData, chartPoint,
                                                 rowPhrase, columnStringBack)
            else:
                detailValid = outDataProcess(outColumn[indexRow], indexRow, rowText, phrase, json_data, detailValid, -1,
                                             discriptionFlag, phraseData, chartPoint, rowPhrase, columnStringBack)
        detailValidTotal.append(detailValid)
    return detailValidTotal, sumColumnFlag


def returnColumnIndex(columnJson, columnString):
    columnIndex = ''
    if columnJson:
        for columnKey in columnJson.keys():
            if str(columnJson[columnKey]).find(columnString) > -1:
                columnIndexBack = str(columnJson[columnKey]).replace(columnString, '')
                if columnIndexBack == '':columnIndexBack = "1"
                if columnIndex == '':
                    columnIndex = columnIndexBack
                else:
                    if int(columnIndex) <= int(columnIndexBack):
                        columnIndex = str(int(columnIndexBack) + 1)
        return columnIndex
    else:
        return columnIndex


def outputData(outValueDict, outColumn, point):
    try:
        if outColumn == "":
            outValue = outValueDict
        else:
            outValue = outValueDict[outColumn]
        if outColumn == "validP" or outColumn == "missingP" or outColumn == "validpercent" or outColumn == "percent" \
                or outColumn == "invalidP" or outColumn == "casepercent" or outColumn == "passRate" or \
                outColumn == "masteryRate" or outColumn == "masteryRateAll" or outColumn == "percentileRank" :
            if point == "":
                return outValue, True
            else:
                if outValue is None:
                    return None, True
                else:
                    return float(str(formatdata(outValue, int(point) + 2))), True
        elif outColumn == "average" or outColumn == "max" or outColumn == "median" or outColumn == "stdev" or \
                outColumn == "variance" or outColumn == "Percent5" or outColumn == "Percent10" or \
                outColumn == "Percent25" or outColumn == "Percent75" or outColumn == "Percent90" or \
                outColumn == "Percent95" or outColumn == "variance_F" or outColumn == "variance_P" or \
                outColumn == "F_T_value" or outColumn == "F_T_P" or outColumn == "Chi_Square_q" or \
                outColumn == "Chi_Square_P" or outColumn == "pearson_r" or outColumn == "pearson_p_value" or \
                outColumn == "spearman_r" or outColumn == "spearman_p_value":
            if point == "" or outValue == "":
                return outValue, False
            else:
                if outValue is None:
                    return None, False
                else:
                    return float(str(formatdata(outValue, int(point)))), False
        elif outColumn == "count":
            return int(outValue), False
        else:
            return outValue, False
    except Exception as e:
        return None, False


def sumDataReturn(augend, andend):
    sumData = None
    if augend is not None:
        if andend is not None:
            sumData = augend + andend
        else:
            sumData = augend
    else:
        if andend is not None:
            sumData = andend
    return sumData


def returnDataSort(detailValidSort, contentSort, rowText):
    if contentSort is not None:
        if contentSort == "id":
            detailValidSort.sort(key=lambda x: x["value"], reverse=False)
        elif contentSort == "-id":
            detailValidSort.sort(key=lambda x: x["value"], reverse=True)
        elif contentSort == "text":
            detailValidSort.sort(key=lambda x: x["text"], reverse=False)
        elif contentSort == "-text":
            detailValidSort.sort(key=lambda x: x["text"], reverse=True)
        elif contentSort == "textNum":
            detailValidSort.sort(key=lambda x: sort_key(x["textColumn"], False), reverse=False)
        elif contentSort == "-textNum":
            detailValidSort.sort(key=lambda x: sort_key(x["textColumn"], True), reverse=True)
        else:
            if str(contentSort).find(",") > -1:
                sortKey, sortWord = str(contentSort).split(','), False
                if str(sortKey[0]).find("-") >= 0: sortWord = True
                for sortKeyIndex, sortKeyItem in enumerate(sortKey):
                    if sortKey[sortKeyIndex].find('id') > -1 or sortKey[sortKeyIndex].find('text') > -1:
                        sortKey[sortKeyIndex] = str(sortKeyItem).replace("-", "")
                        if sortKey[sortKeyIndex] == 'id': sortKey[sortKeyIndex] = 'value'
                    else:
                        if str(sortKey[sortKeyIndex]).strip() == '':
                            sortKey[sortKeyIndex] = "column0"
                        else:
                            if rowText != "":
                                sortKey[sortKeyIndex] = "column" + str(int(str(sortKeyItem).replace("-", "")) - 1)
                            else:
                                sortKey[sortKeyIndex] = "column" + str(sortKeyItem).replace("-", "")
                if len(sortKey) == 2:
                    detailValidSort.sort(key=lambda x: (sort_key(x[str(sortKey[0])], sortWord),
                                                        sort_key(x[str(sortKey[1])], sortWord)), reverse=sortWord)
                else:
                    detailValidSort.sort(key=lambda x: (sort_key(x[str(sortKey[0])], sortWord),
                                                        sort_key(x[str(sortKey[1])], sortWord),
                                                        sort_key(x[str(sortKey[2])], sortWord)),reverse=sortWord)
            else:
                if str(contentSort).find('id') > -1 or str(contentSort).find('text') > -1:
                    sortKey = str(contentSort).replace("-", "")
                    if sortKey == 'id': sortKey = 'value'
                else:
                    if rowText != "":
                        sortKey = "column" + str(int(str(contentSort).replace("-", "")) - 1)
                    else:
                        sortKey = "column" + str(contentSort).replace("-", "")
                if str(contentSort).find("-") >= 0:
                    detailValidSort.sort(key=lambda x: sort_key(x[str(sortKey)], True), reverse=True)
                else:
                    detailValidSort.sort(key=lambda x: sort_key(x[str(sortKey)], False), reverse=False)
    else:
        if rowText != "":
            detailValidSort.sort(key=lambda x: x["value"], reverse=False)
    return detailValidSort


def outputFormatData(outValue, columnName, point, indexColumn, unitsBefore, unitsAfter, replaceText, rowIndex):
    columnName = columnName.replace('固定值', '')
    if outValue is None:
        outFormatData = ""
    elif outValue == "index":
        outFormatData = str(rowIndex)
    elif isinstance(outValue, str) and outValue.strip() == "":
        outFormatData = ""
    else:
        pointInt = 2
        if isinstance(outValue, float) or isinstance(outValue, int):
            if isinstance(point, list) and len(point) > 0:
                if point[0] is None:
                    outFormatData = formatdata(outValue, pointInt)
                else:
                    if len(point) > indexColumn:
                        if point[indexColumn] != "" : pointInt = point[indexColumn]
                    else:
                        if point[len(point) - 1] != "": pointInt = point[len(point) - 1]
                    outFormatData = formatdata(outValue, pointInt)
            else:
                if columnName == "validP" or columnName == "missingP" or columnName == "validpercent" or \
                        columnName == "percent" or columnName == "invalidP" or columnName == "casepercent" or \
                        columnName == "passRate" or columnName == "masteryRate" or columnName == "masteryRateAll" or \
                        columnName == "percentileRank" or columnName == "average" or columnName == "max" or \
                        columnName == "min" or columnName == "median" or columnName == "stdev" or \
                        columnName == "variance" or str(columnName).find("Percent") > -1 or columnName == "sum" or \
                        columnName == "mode" or columnName == "variance_F" or columnName == "variance_P" or \
                        columnName == "F_T_value" or columnName == "F_T_P" or columnName == "Chi_Square_q" or \
                        columnName == "Chi_Square_P" or columnName == "pearson_r" or columnName == "pearson_p_value" or \
                        columnName == "spearman_r" or columnName == "spearman_p_value":
                    if check_json_format(json.dumps(point)):
                        if "point" in point.keys() : pointInt = point["point"]
                        if columnName in point.keys(): pointInt = point[columnName]
                        outFormatData = formatdata(outValue, pointInt)
                    else:
                        outFormatData = formatdata(outValue, point)
                elif columnName == "count" or columnName == "sort":
                    outFormatData = str(int(outValue))
                else:
                    outFormatData = str(outValue)
        else:
            outFormatData = str(outValue)

        if isinstance(unitsAfter, list) and len(unitsAfter) > 0:
            if len(unitsAfter) > indexColumn and unitsAfter[0] is not None:
                outFormatData = outFormatData + unitsAfter[indexColumn]
        elif check_json_format(json.dumps(unitsAfter)):
            if columnName in unitsAfter.keys(): outFormatData = outFormatData + unitsAfter[columnName]
        else:
            if is_number(outValue):outFormatData = outFormatData + unitsAfter
        if isinstance(unitsBefore, list) and len(unitsBefore) > 0:
            if len(unitsBefore) > indexColumn and unitsBefore[0] is not None:
                outFormatData = unitsBefore[indexColumn] + outFormatData
        elif check_json_format(json.dumps(unitsBefore)):
            if columnName in unitsBefore.keys(): outFormatData = unitsBefore[columnName] + outFormatData
        else:
            outFormatData = unitsBefore + outFormatData
        if isinstance(replaceText, list):
            replaceFrom = replaceText[0]
            replaceTo = replaceText[1]
            for replaceIndex,replaceItem in enumerate(replaceFrom):
                if outFormatData.strip() == str(replaceItem).strip() and replaceIndex < len(replaceTo):
                    if replaceTo[replaceIndex] is None:
                        outFormatData = ""
                    else:
                        outFormatData = replaceTo[replaceIndex]
    return outFormatData


def pptxtable(documentPptx, contentRow, json_data, tableHead, slideDelete, sameRowTable, replaceTable):
    content = contentRow["content"]
    datadef = lambda: None if "data" not in content.keys() else content["data"]
    pointdef = lambda:2 if "point" not in content.keys() else content["point"]
    unitsdef = lambda:"" if "units" not in content.keys() else content["units"]
    rowStardef = lambda:1 if "rowStar" not in content.keys() else int(content["rowStar"])
    colStardef = lambda:0 if "colStar" not in content.keys() else int(content["colStar"])
    bolddef = lambda:"" if "bold" not in content.keys() else content["bold"]
    phrasedef = lambda: "" if "phrase" not in content.keys() else content["phrase"]
    point,units,rowStar,colStar,bold,table,dataN,phrase,tablePosition = \
        pointdef(),unitsdef(),rowStardef(),colStardef(),bolddef(),None,datadef(),phrasedef(), ""
    if "index" in content.keys():
        for slide in documentPptx.slides:
            for shapeIndex, shape in enumerate(slide.shapes):
                if shape.has_table and shapeIndex == int(content["index"]):
                    table = shape.table
    else:
        if str(content["flag"]).strip().find("表") >= 0:
            tablePosition = str(content["flag"]).strip()
        else:
            tablePosition = "[表" + str(content["flag"]).strip() + "]"
        for slide in documentPptx.slides:
            text_shapes, chart_shapes, table_shapes = [], [], []
            for shape in slide.shapes:
                iter_shape(shape, text_shapes, chart_shapes, table_shapes)
            for shape in table_shapes:
                if len(shape.table.rows) > rowStar and len(shape.table.columns) > colStar:
                    try:
                        if str(shape.table.cell(rowStar, colStar).text).find(tablePosition) > -1:
                            table = shape.table
                            break
                    except Exception as e:
                        pass
        if tablePosition == "[表2]":
            testFlag = True
        if table is None:
            for slide in documentPptx.slides:
                text_shapes, chart_shapes, table_shapes = [], [], []
                for shape in slide.shapes:
                    iter_shape(shape, text_shapes, chart_shapes, table_shapes)
                for shape in table_shapes:
                    for rowIndex in range(len(shape.table.rows)):
                        for colIndex in range(len(shape.table.columns)):
                            try:
                                if str(shape.table.cell(rowIndex, colIndex).text).find(tablePosition) > -1:
                                    table,rowStar,colStar = shape.table, rowIndex, colIndex
                                    break
                            except Exception as e:
                                pass
                        if table:break
                    if table: break
                if table: break
    if table:
        count, sameRowPosition, sameRowTableIndex, sameRowPositionDict = 0, [], -1, {}
        for colIndex in range(0, len(table.columns)):
            tableText = ''
            try:
                for paragraph in table.rows[rowStar].cells[colIndex].paragraphs:
                    tableText += paragraph.text.strip()
            except Exception as e:
                pass
            if tableText.find('[表') > -1 and tableText.find(']') > -1 and tableText not in sameRowPosition:
                sameRowPositionDict[tableText] = 0
                sameRowPosition.append(tableText)
        for sameRowTableItem in sameRowTable:
            for key in sameRowTableItem.keys():
                if key in sameRowPosition: sameRowPosition.remove(key)
        if len(sameRowPosition) > 1:
            sameRowTable.append(sameRowPositionDict)
        for sameRowTableI, sameRowTableItem in enumerate(sameRowTable):
            if tablePosition in sameRowTableItem.keys():
                sameRowTableIndex = sameRowTableI
                break
        if tableHead is not None:
            position = tableHead["position"]
            for positionIndex, positionItem in enumerate(position):
                if tablePosition == str(positionItem):
                    table_cell_set(table, tableHead["cell"][positionIndex][0], tableHead["cell"][positionIndex][1],
                                   tableHead["cell"][positionIndex][0], str(tableHead["content"][positionIndex]))

        rowPhrasedef = lambda: "" if "rowPhrase" not in content.keys() else content["rowPhrase"]
        rowTextdef = lambda: "" if "rowText" not in content.keys() else content["rowText"]
        outColumndef = lambda: "" if "outColumn" not in content.keys() else content["outColumn"]
        unitsBeforedef = lambda: "" if "unitsBefore" not in content.keys() else content["unitsBefore"]
        unitsAfterdef = lambda: "" if "unitsAfter" not in content.keys() else content["unitsAfter"]
        sortFirstdef = lambda: [] if "sortFirst" not in content.keys() else content["sortFirst"]
        sortLastdef = lambda: [] if "sortLast" not in content.keys() else content["sortLast"]
        positiondef = lambda: "" if "position" not in content.keys() else content["position"]
        sumColumndef = lambda: "" if "sumColumn" not in content.keys() else content["sumColumn"]
        replaceTextdef = lambda: "" if "replaceText" not in content.keys() else content["replaceText"]
        zeroFilldef = lambda: "" if "zeroFill" not in content.keys() else str(content["zeroFill"])
        phraseDatadef = lambda: "" if "phraseData" not in content.keys() else content["phraseData"]
        colEnddef = lambda: "" if "colEnd" not in content.keys() else str(content["colEnd"])
        tableHeaddef = lambda: "" if "tableHead" not in content.keys() else content["tableHead"]
        rowPhrase, rowTextAll, outColumn, unitsBefore, unitsAfter, fromtext, detailValid, columnMax, phraseData = \
            rowPhrasedef(), rowTextdef(), outColumndef(), unitsBeforedef(), unitsAfterdef(), "表", [], 0, phraseDatadef()
        sortFirst, sortLast, position, detailValidTotal, sumColumn, sumColumnData, replaceText, zeroFill = \
            sortFirstdef(), sortLastdef(), positiondef(), [], sumColumndef(), [], replaceTextdef(), zeroFilldef()
        orderColumn, orderPoint, orderKey, sumColumnName, columnStringBack, breakCount, colEnd, maxrow = \
            "", 0, 0, [], {}, 1, colEnddef(), 0
        mergerStardef = lambda: None if "mergerStar" not in content.keys() else content["mergerStar"]
        mergerEnddef = lambda: None if "mergerEnd" not in content.keys() else content["mergerEnd"]
        mergerColumndef = lambda: None if "mergerColumn" not in content.keys() else content["mergerColumn"]
        addrowdef = lambda: None if "addrow" not in content.keys() else str(content["addrow"])
        mergerStar, mergerEnd, mergerColumn, addrow, tableHead, tableHeadRemove, sumColumnFlag = \
            mergerStardef(), mergerEnddef(), mergerColumndef(), addrowdef(), tableHeaddef(), [], False
        mergerColumnNM, columnMerger, mergerRowStar, mergerRowEnd, mergerColumnGroup, mergerCount, remainderRow = \
            [], [], [], [], [], [], -1
        if len(sortFirst) == 0 and len(sortLast) == 0:
            rowNo, sortAll = 0, []
        else:
            if len(sortFirst) != 0:
                rowNo, sortAll = -99999, sortFirst
            else:
                rowNo, sortAll = 99999, sortLast
        if isinstance(rowTextAll, list):
            rowText = rowTextAll[0]
        else:
            rowText = rowTextAll
        if rowText != "":
            detailValidTotal, sumColumnFlag = rowDataProcess(outColumn, rowText, phrase, rowPhrase, rowNo, sortAll,
                                                             json_data, False, phraseData, "", sumColumn)
        else:
            for columnIndex in range(len(outColumn)):
                detailValid.append(dict(value=int(columnIndex + 1)))
                if isinstance(outColumn[columnIndex], list):
                    if len(outColumn[columnIndex]) > columnMax: columnMax = len(outColumn[columnIndex])
                    for indexCol in range(len(outColumn[columnIndex])):
                        detailValid = outDataProcess(outColumn[columnIndex][indexCol], indexCol, rowText, phrase,
                                                     json_data, detailValid, columnIndex, False, phraseData, "",
                                                     rowPhrase, columnStringBack)
                else:
                    if len(outColumn) > columnMax: columnMax = len(outColumn)
                    detailValid = outDataProcess(outColumn[columnIndex], columnIndex, rowText, phrase, json_data,
                                                 detailValid, -1, False, phraseData, "", rowPhrase, columnStringBack)
            detailValidTotal.append(detailValid)
        if isinstance(replaceText, list):
            for detailValidTotalIndex in range(len(detailValidTotal)):
                for detailIndex in range(len(detailValidTotal[detailValidTotalIndex])):
                    for keyDetail, valueDetail in detailValidTotal[detailValidTotalIndex][detailIndex].items():
                        replaceFrom, replaceTo = replaceText[0], replaceText[1]
                        for replaceIndex, replaceItem in enumerate(replaceFrom):
                            if str(valueDetail).strip() == str(replaceItem).strip() and \
                                    replaceIndex < len(replaceTo):
                                if replaceTo[replaceIndex] is None:
                                    detailValidTotal[detailValidTotalIndex][detailIndex][keyDetail] = ""
                                else:
                                    detailValidTotal[detailValidTotalIndex][detailIndex][keyDetail] = \
                                        replaceTo[replaceIndex]
            for detailValidTotalIndex in range(len(detailValidTotal)):
                if len(detailValidTotal[detailValidTotalIndex]) > 0 and \
                        'phrase' in detailValidTotal[detailValidTotalIndex][0].keys() and \
                        detailValidTotalIndex < len(detailValidTotal) - 1 and \
                        len(detailValidTotal[detailValidTotalIndex + 1]) > 0 and \
                        'phrase' in detailValidTotal[detailValidTotalIndex + 1][0].keys() and \
                        detailValidTotal[detailValidTotalIndex][0]['phrase'] == \
                        detailValidTotal[detailValidTotalIndex + 1][0]['phrase']:
                    valueIndex = -1
                    if 'value' in detailValidTotal[detailValidTotalIndex][0].keys():
                        valueIndex = \
                            detailValidTotal[detailValidTotalIndex][len(detailValidTotal[detailValidTotalIndex]) - 1][
                                'value']
                    for detailIndex in range(len(detailValidTotal[detailValidTotalIndex + 1])):
                        if valueIndex != -1:
                            valueIndex += 1
                            detailValidTotal[detailValidTotalIndex + 1][detailIndex]['value'] = valueIndex
                        detailValidTotal[detailValidTotalIndex].append \
                            (detailValidTotal[detailValidTotalIndex + 1][detailIndex])
                    detailValidTotal[detailValidTotalIndex + 1] = []
            detailValidTotal = list(filter(None, detailValidTotal))
        if isinstance(rowPhrase, list) and str(rowPhrase).find('textRow,textColumn') > 0 and \
                len(rowPhrase) > 1 and len(detailValidTotal[0]) > 0 and 'phrase' in detailValidTotal[0][0].keys():
            if "sort" in content.keys():
                if content["sort"].find('id') > -1:
                    content["sort"] = content["sort"].replace(',id', '').replace(',-id', '').replace('id,', ''). \
                        replace('-id,', '')
                else:
                    for detailIndex in range(len(detailValidTotal)):
                        detailValidTotal[detailIndex] = returnDataSort(detailValidTotal[detailIndex],
                                                                       content["sort"], rowText)
        if sumColumnFlag and 'phrase' in detailValidTotal[0][0].keys():
            detailValidTotalNew, detailSaveFlag = regroup_array_by_key(detailValidTotal, 'phrase', sumColumn)
            if detailSaveFlag:
                detailValidRemove, detailValidReduction = [], 0
                for detailValidTotalIndex, detailValidTotalItem in enumerate(detailValidTotalNew):
                    if detailValidTotalIndex % 2 == 0:
                        detailValidReduction = 1
                    else:
                        detailValidReduction = -1
                    if 'text' in detailValidTotalItem[0].keys() and \
                            str(detailValidTotalItem[0]['text']).find('保留】') > -1:
                        detailValidTotalNew[detailValidTotalIndex][0]['text'] = \
                            str(detailValidTotalItem[0]['text']).replace('【保留】', '').replace('【明细保留】', '')
                        if len(detailValidTotalNew[detailValidTotalIndex + detailValidReduction]) == 1:
                            if str(detailValidTotalItem[0]['text']).find('【保留】') > -1:
                                detailValidRemove. \
                                    append(detailValidTotalNew[detailValidTotalIndex + detailValidReduction])
                            else:
                                detailValidRemove.append(detailValidTotalItem)
                for itemRemove in detailValidRemove:
                    detailValidTotalNew.remove(itemRemove)
            if len(detailValidTotalNew) > 0: detailValidTotal = detailValidTotalNew
            sumColumn = ''
        detailValidTotalFlag = False
        if isinstance(rowPhrase, str) and rowPhrase.find('textRow,textColumn') > 0 and not sumColumnFlag:
            detailValidTotalFlag = True
        if not detailValidTotalFlag and not sumColumnFlag and isinstance(rowPhrase, list):
            textFlag, textRowFlag = False, False
            for rowPhraseItem in rowPhrase:
                if rowPhraseItem.find('textRow,textColumn') > 0: textRowFlag = True
                if rowPhraseItem.find('text') > 0 and rowPhraseItem.find('textRow,textColumn') < 0: textFlag = True
            if not textFlag and textRowFlag: detailValidTotalFlag = True
        if detailValidTotalFlag:
            detailValidTotalNew, detailValidTotalItemNew, phraseBreak = [], [], ''
            for detailIndex in range(len(detailValidTotal)):
                if len(detailValidTotal[detailIndex]) > 0 and 'phrase' in detailValidTotal[detailIndex][0].keys():
                    for detailItem in detailValidTotal[detailIndex]:
                        if phraseBreak != detailItem['phrase']:
                            if len(detailValidTotalItemNew) != 0:
                                detailValidTotalNew.append(copy.deepcopy(detailValidTotalItemNew))
                                detailValidTotalItemNew.clear()
                        detailValidTotalItemNew.append(detailItem)
                        phraseBreak = detailItem['phrase']
                    if len(detailValidTotalItemNew) != 0:
                        detailValidTotalNew.append(copy.deepcopy(detailValidTotalItemNew))
                        detailValidTotalItemNew.clear()
                else:
                    detailValidTotalNew.append(copy.deepcopy(detailValidTotal[detailIndex]))
            if len(detailValidTotalNew) > 0: detailValidTotal = detailValidTotalNew
        for detailIndex in range(len(detailValidTotal)):
            if rowText != "":
                for detailItem in detailValidTotal[detailIndex]:
                    if detailItem["columnMax"] > columnMax: columnMax = detailItem["columnMax"]
            if "sort" in content.keys():
                detailValidTotal[detailIndex] = returnDataSort(detailValidTotal[detailIndex], content["sort"],
                                                               rowText)
            else:
                detailValidTotal[detailIndex] = returnDataSort(detailValidTotal[detailIndex], None, rowText)
        if sumColumn != "":
            for sumIndex in range(columnMax):
                sumColumnData.append(0)
                sumColumnName.append("")
        if mergerColumn is not None:
            for mergerIndex in range(len(mergerColumn)):
                mergerColumnNM.append("")
                columnMerger.append("")
                mergerRowStar.append([])
                mergerRowEnd.append([])
                mergerColumnGroup.append("")
                mergerCount.append("0")
        textRow, indexStar, tableColAdd, rowIndex, addColumnMax, mergerRowSave, mergerColSave = \
            ["text"], 0, 1, 0, columnMax, [], []
        if isinstance(rowTextAll, list) and rowTextAll[1] != "":
            rowText = ""
        if rowText == "":
            textRow, indexStar, tableColAdd = ["column0"], 1, 0
        if mergerColumn is not None and len(mergerColumn) > 0:
            for mergerColumnIndex, mergerColumnItem in enumerate(mergerColumn):
                if mergerColumnItem.find('column') > -1:
                    mergerColumn[mergerColumnIndex] = \
                        'column' + str(int(mergerColumnItem.replace('column', '')) - 1 + indexStar)
        if (isinstance(rowPhrase, list) and len(rowPhrase) > 0) or \
                (isinstance(rowPhrase, str) and rowPhrase.find("data") > -1 and rowPhrase.find(":") > -1):
            textRow, tableColAdd = ["phrase", "text"], 2
            if rowText == "":
                textRow, tableColAdd = ["phrase", "column0"], 1
        if (isinstance(rowPhrase, str) and rowPhrase.find("data") > -1 and rowPhrase.find(":") > -1 and
            rowPhrase.find(";") > -1) or (isinstance(rowPhrase, list) and rowPhrase[0].find("data") > -1 and
                                          rowPhrase[0].find(":") > -1 and rowPhrase[0].find(";") > -1):
            textRow, tableColAdd = ["headPhrase", "phrase", "text"], 3
        if isinstance(point, list):
            if len(point) > orderKey + tableColAdd:
                orderPoint = point[orderKey + tableColAdd]
            else:
                orderPoint = point[len(point) - 1]
        else:
            orderPoint = point
        if isinstance(tableHead, list) and len(tableHead) > 0:
            if isinstance(tableHead[0], list):
                tableHeadLength = len(tableHead[0])
            else:
                tableHeadLength = len(tableHead)
            for tableHeadIndex in range(tableHeadLength):
                tableHeadRemove.append(True)
        for detailValidTotalIndex, detailValidTotalItem in enumerate(detailValidTotal):
            detailRemove, detailLast, detailFirst = [], [], []
            if len(sortLast) > 0:
                detailLast = sortLast
                detailLast.reverse()
            if len(sortFirst) > 0:
                detailFirst = sortFirst
                detailFirst.reverse()
            for detailIndex, detailItem in enumerate(detailValidTotalItem):
                removeFlag = True
                for indexColumn in range(columnMax):
                    colRemoveFlag = True
                    if str(detailItem["columnName" + str(indexColumn)]).strip().find("固定值") > 1 and colEnd != '':
                        detailItem["columnName" + str(indexColumn)] = \
                            str(detailItem["columnName" + str(indexColumn)]).strip().replace('固定值', '')
                    if isinstance(outColumn[0], list):
                        if is_fromData(str(outColumn[detailItem["rowIndex"]][indexColumn])) and \
                                detailItem["column" + str(indexColumn)] is not None and \
                                detailItem["column" + str(indexColumn)] != "" and \
                                not str(detailItem["columnName" + str(indexColumn)]).strip().find("固定值") > -1 and \
                                ((is_number(sort_key(detailItem["column" + str(indexColumn)], None)) and
                                  float(str(sort_key(detailItem["column" + str(indexColumn)], None))) != 0.0) or
                                 (str(detailItem["columnName" + str(indexColumn)]).find("text") > -1 and
                                  detailItem["column" + str(indexColumn)] != "")):
                            removeFlag, colRemoveFlag = False, False
                    else:
                        if is_fromData(str(outColumn[indexColumn])) and \
                                detailItem["column" + str(indexColumn)] is not None and \
                                detailItem["column" + str(indexColumn)] != "" and \
                                not str(detailItem["columnName" + str(indexColumn)]).strip().find("固定值") > -1 and \
                                ((is_number(sort_key(detailItem["column" + str(indexColumn)], None)) and
                                  float(str(sort_key(detailItem["column" + str(indexColumn)], None))) != 0.0) or
                                 (str(detailItem["columnName" + str(indexColumn)]).find("text") > -1 and
                                  detailItem["column" + str(indexColumn)] != "")):
                            removeFlag, colRemoveFlag = False, False
                    if len(tableHeadRemove) > 0 and indexStar <= indexColumn < len(tableHeadRemove) and \
                            tableHeadRemove[indexColumn - indexStar] and not colRemoveFlag:
                        tableHeadRemove[indexColumn - indexStar] = False
                    if not removeFlag and \
                            ((0 < len(tableHeadRemove) and
                              all(tableHeadRemoveItem is False for tableHeadRemoveItem in tableHeadRemove)) or
                             len(tableHeadRemove) == 0): break
                if removeFlag:
                    removeFlag = False
                    for indexColumn in range(columnMax):
                        if not str(detailItem["columnName" + str(indexColumn)]).strip().find("固定值") > -1:
                            removeFlag = True
                            break
                if zeroFill != "":
                    for indexColumn in range(columnMax):
                        if detailItem["column" + str(indexColumn)] is None:
                            if zeroFill == 'true' or zeroFill == '0':
                                detailValidTotal[detailValidTotalIndex][detailIndex][
                                    "column" + str(indexColumn)] = 0
                            else:
                                detailValidTotal[detailValidTotalIndex][detailIndex][
                                    "column" + str(indexColumn)] = zeroFill
                if removeFlag:
                    detailRemove.append(detailItem)
                else:
                    if rowText == "":
                        sortLastText = str(detailItem["column0"]).strip()
                    else:
                        sortLastText = str(detailItem["text"]).strip()
                    if sortLastText in sortFirst:
                        for sortFirstIndex, sortFirstItem in enumerate(detailFirst):
                            if isinstance(sortFirstItem, str) and sortLastText == sortFirstItem:
                                detailRemove.append(detailItem)
                                detailFirst[sortFirstIndex] = detailItem
                    if sortLastText in sortLast:
                        for sortLastIndex, sortLastItem in enumerate(detailLast):
                            if isinstance(sortLastItem, str) and sortLastText == sortLastItem:
                                detailRemove.append(detailItem)
                                detailLast[sortLastIndex] = detailItem
            detailSaveFlag = ''
            for detailItem in detailValidTotalItem:
                if 'text' in detailItem.keys() and str(detailItem['text']).find('【保留】') > -1:
                    detailSaveFlag = '【保留】'
                if 'text' in detailItem.keys() and str(detailItem['text']).find('【明细保留】') > -1:
                    detailSaveFlag = '【明细保留】'
            if len(detailValidTotalItem) - len(detailRemove) == 2 and detailSaveFlag != '':
                for detailItem in detailValidTotalItem:
                    if detailSaveFlag == '【保留】' and str(detailItem['text']).find('【保留】') < 0:
                        detailRemove.append(detailItem)
                    if detailSaveFlag == '【明细保留】' and str(detailItem['text']).find('【明细保留】') > -1:
                        detailRemove.append(detailItem)
            for itemRemove in detailRemove:
                detailValidTotalItem.remove(itemRemove)
            for itemLast in detailLast:
                if isinstance(itemLast, dict): detailValidTotalItem.append(itemLast)
            for itemFirst in detailFirst:
                if isinstance(itemFirst, dict): detailValidTotalItem.insert(0, itemFirst)
            for detailIndex, detailItem in enumerate(detailValidTotalItem):
                if detailSaveFlag != '':
                    detailValidTotal[detailValidTotalIndex][detailIndex]['text'] = \
                        detailItem['text'].replace(detailSaveFlag, '')
                if isinstance(rowPhrase, list) and len(rowPhrase) > 0 and 'phrase' in detailItem.keys() and \
                        'text' in detailItem.keys():
                    detailValidTotal[detailValidTotalIndex][detailIndex]['text'] = \
                        detailItem['text'].replace('（' + str(detailItem['phrase']) + '）', '')
        detailValidTotal = list(filter(None, detailValidTotal))
        if "breakdown" in content.keys():
            maxrow = len(detailValidTotal[0]) // int(content["breakdown"]) + rowStardef() - 1
            if len(detailValidTotal[0]) % int(content["breakdown"]) > 0:
                maxrow += 1
                remainderRow = len(detailValidTotal[0]) % int(content["breakdown"])
            breakCount = int(content["breakdown"])
        if len(tableHeadRemove) > 0:
            for tableHeadRemoveItem in tableHeadRemove:
                if tableHeadRemoveItem:
                    addColumnMax -= 1
        if len(table.columns) - colStardef() < breakCount * (columnMax + tableColAdd):
            if colEnd == "":
                columnEnd, style, columnWidth = table.columns[len(table.columns) - 1], [], []
                for rowIndex in range(len(table.rows)):
                    paragraphs = table.cell(rowIndex, len(table.columns) - 1).paragraphs
                    style.append(paragraphs[0].style)
                for columnIndex in range(len(table.columns)):
                    columnWidth.append(table.columns[columnIndex].width)
                for n in range(breakCount * (addColumnMax + tableColAdd) - (len(table.columns) - colStardef())):
                    table.add_column(columnEnd.width)
                    for rowIndex in range(len(table.rows)):
                        table.cell(rowIndex, len(table.columns) - 1).paragraphs[0].style = style[rowIndex]
                        table.cell(rowIndex, len(table.columns) - 1).vertical_alignment = \
                            table.cell(rowIndex, len(table.columns) - 2).vertical_alignment
                for rowIndex in range(len(table.rows)):
                    for columnIndex in range(len(table.columns)):
                        if columnIndex < len(columnWidth):
                            table.cell(rowIndex, columnIndex).width = columnWidth[columnIndex]
                        else:
                            table.cell(rowIndex, columnIndex).width = columnEnd.width
            else:
                colDifference = breakCount * (columnMax + tableColAdd) - (len(table.columns) - colStardef())
                columnMax = columnMax - int(colDifference / breakCount)
        try:
            if len(tableHeadRemove) > 0:
                if isinstance(tableHead[0], list):
                    tableHeadStar = len(tableHead)
                    for tableHeadItem in tableHead:
                        if len(tableHeadItem) == 0: tableHeadStar -= 1
                    headRowStar = rowStardef() - tableHeadStar
                else:
                    headRowStar = rowStardef() - 1
                if mergerStar is not None:
                    headIndexStar = 0
                    for mergerStarInd, mergerStarItem in enumerate(mergerStar):
                        if isinstance(mergerStarItem, list) and int(mergerStarItem[0]) < rowStardef():
                            headIndexEnd = headIndexStar + \
                                           int(mergerEnd[mergerStarInd][1]) - int(mergerStarItem[1]) + 1
                            headIndexRemove = 0
                            for headIndex in range(headIndexStar, headIndexEnd):
                                if tableHeadRemove[headIndex]:
                                    headIndexRemove += 1
                            headIndexStar = int(mergerEnd[mergerStarInd][1]) - int(mergerStarItem[1]) + 1
                            mergerEnd[mergerStarInd][1] = int(mergerEnd[mergerStarInd][1]) - headIndexRemove
                            if headIndexRemove > 0:
                                for mergerStarEndIndex in range(mergerStarInd + 1, len(mergerStar)):
                                    mergerStar[mergerStarEndIndex][1] = \
                                        int(mergerStar[mergerStarEndIndex][1]) - headIndexRemove
                                    mergerEnd[mergerStarEndIndex][1] = \
                                        int(mergerEnd[mergerStarEndIndex][1]) - headIndexRemove
                for headRowIndex in range(headRowStar, rowStardef()):
                    tableIndexStar = 0
                    for indexColumn in range(columnMax - indexStar):
                        if isinstance(tableHead[0], list):
                            tableHeadText = tableHead[headRowIndex][indexColumn]
                            if indexColumn > 0 and tableHeadText == tableHead[headRowIndex][indexColumn - 1]:
                                tableHeadText = ''
                        else:
                            tableHeadText = tableHead[indexColumn]
                            if indexColumn > 0 and tableHeadText == tableHead[indexColumn - 1]:
                                tableHeadText = ''
                        if not (len(tableHeadRemove) > 0 and indexColumn < len(tableHeadRemove) and
                                tableHeadRemove[indexColumn]):
                            table_cell_set(table, headRowIndex, colStar + tableIndexStar + tableColAdd + indexStar,
                                           headRowStar, tableHeadText)
                            tableIndexStar += 1
            for detailTotalIndex in range(len(detailValidTotal)):
                if sumColumn != "" and detailTotalIndex > 0:
                    for sumIndex in range(columnMax):
                        sumColumnData[sumIndex] = 0
                        sumColumnName[sumIndex] = ""
                detailValid = detailValidTotal[detailTotalIndex]
                if addrow is not None and is_number_int(addrow) and int(addrow) > 0 and orderColumn != "":
                    if isinstance(rowTextAll, list) and rowTextAll[1] != "":
                        addrow = returncountRepeat(detailValid, int(addrow), orderColumn, orderPoint)
                    else:
                        addrow = returncount(detailValid, int(addrow), orderColumn, orderPoint)
                if isinstance(rowTextAll, list) and rowTextAll[1] == "True" and addrow < len(detailValid):
                    detailValidRepeat = []
                    for indexRemove in range(addrow - 1, -1, -1):
                        detailValidRepeat.append(detailValid[indexRemove])
                    detailValid = detailValidRepeat
                for detailIndex, detailItem in enumerate(detailValid):
                    rowIndex += 1
                    if addrow is not None and is_number_int(addrow) and int(addrow) != 0:
                        if rowStar > int(addrow):
                            break
                    if (addrow is None or (addrow is not None and is_number_int(addrow) and int(addrow) != 0)) and \
                            len(table.rows) <= rowStar:
                        break
                    for textIndex in range(len(textRow)):
                        outputFlag, mergerFlag = False, False
                        if mergerColumn is not None:
                            for mergerIndex in range(len(mergerColumn)):
                                if str(mergerColumn[mergerIndex]).strip() == textRow[textIndex]:
                                    mergerFlag = True
                                    if str(detailItem[mergerColumn[mergerIndex]]).strip() != mergerColumnGroup[
                                        mergerIndex]:
                                        mergerColumnGroup[mergerIndex] = str(
                                            detailItem[mergerColumn[mergerIndex]]).strip()
                                        outputFlag = True
                        if textRow[textIndex] == "column0":
                            textRowName = detailItem["columnName0"]
                        else:
                            textRowName = textRow[textIndex]
                        if not mergerFlag:
                            table_cell_set(table, rowStar, colStar + textIndex, rowStardef(),
                                           outputFormatData(detailItem[textRow[textIndex]], textRowName, point,
                                                            textIndex, unitsBefore, unitsAfter, replaceText, rowIndex))
                        else:
                            if outputFlag:
                                table_cell_set(table, rowStar, colStar + textIndex, rowStardef(),
                                               outputFormatData(detailItem[textRow[textIndex]], textRowName, point,
                                                                textIndex, unitsBefore, unitsAfter, replaceText,
                                                                rowIndex))
                            else:
                                table_cell_set(table, rowStar, colStar + textIndex, rowStardef(), "")
                        if mergerColumn is not None:
                            for mergerIndex in range(len(mergerColumn)):
                                if textRow[textIndex] == str(mergerColumn[mergerIndex]):
                                    columnMerger[mergerIndex] = str(colStar + textIndex)
                                    if mergerColumnNM[mergerIndex] != str(detailItem[textRow[textIndex]]).strip():
                                        mergerRowStar[mergerIndex].append(str(rowStar))
                                    if mergerColumnNM[mergerIndex].strip() != "" and \
                                            mergerColumnNM[mergerIndex] != str(detailItem[textRow[textIndex]]).strip():
                                        mergerRowEnd[mergerIndex].append(str(rowStar - 1))
                                    mergerColumnNM[mergerIndex] = str(detailItem[textRow[textIndex]]).strip()
                                    columnMerger[mergerIndex] = str(colStar + textIndex)
                                    break
                    for indexColumn in range(indexStar, columnMax):
                        if len(tableHeadRemove) > 0 and -1 < indexColumn - indexStar < len(tableHeadRemove) and \
                                tableHeadRemove[indexColumn - indexStar]:
                            continue
                        outputFlag, mergerFlag = False, False
                        if mergerColumn is not None:
                            for mergerIndex in range(len(mergerColumn)):
                                if str(mergerColumn[mergerIndex]).strip() == "column" + str(indexColumn):
                                    mergerFlag = True
                                    if str(detailItem[mergerColumn[mergerIndex]]).strip() != mergerColumnGroup[
                                        mergerIndex]:
                                        mergerColumnGroup[mergerIndex] = str(
                                            detailItem[mergerColumn[mergerIndex]]).strip()
                                        outputFlag = True
                        if not mergerFlag:
                            table_cell_set(table, rowStar, colStar + indexColumn + tableColAdd, rowStardef(),
                                           outputFormatData(detailItem["column" + str(indexColumn)],
                                                            detailItem["columnName" + str(indexColumn)], point,
                                                            indexColumn + tableColAdd, unitsBefore, unitsAfter,
                                                            replaceText, rowIndex))
                        else:
                            if outputFlag:
                                table_cell_set(table, rowStar, colStar + indexColumn + tableColAdd, rowStardef(),
                                               outputFormatData(detailItem["column" + str(indexColumn)],
                                                                detailItem["columnName" + str(indexColumn)], point,
                                                                indexColumn + tableColAdd, unitsBefore, unitsAfter,
                                                                replaceText, rowIndex))
                            else:
                                table_cell_set(table, rowStar, colStar + indexColumn + tableColAdd, rowStardef(), "")
                        if sumColumn != "":
                            if detailItem["column" + str(indexColumn)] is not None and \
                                    is_number(detailItem["column" + str(indexColumn)]):
                                sumColumnData[indexColumn] += detailItem["column" + str(indexColumn)]
                            sumColumnName[indexColumn] = detailItem["columnName" + str(indexColumn)]
                        if mergerColumn is not None:
                            for mergerIndex in range(len(mergerColumn)):
                                if "column" + str(indexColumn).strip() == str(mergerColumn[mergerIndex]):
                                    columnMerger[mergerIndex] = str(colStar + indexColumn + tableColAdd)
                                    if mergerColumnNM[mergerIndex] != str(
                                            detailItem["column" + str(indexColumn)]).strip():
                                        mergerRowStar[mergerIndex].append(str(rowStar))
                                    if mergerColumnNM[mergerIndex].strip() != "" and mergerColumnNM[mergerIndex] != \
                                            str(detailItem["column" + str(indexColumn)]).strip():
                                        mergerRowEnd[mergerIndex].append(str(rowStar - 1))
                                    mergerColumnNM[mergerIndex] = str(detailItem["column" + str(indexColumn)]).strip()
                                    columnMerger[mergerIndex] = str(colStar + indexColumn + tableColAdd)
                                    break
                    table_setAll_colorBgFont_bold(table, rowStar, content, replaceTable)
                    if "breakdown" in content.keys():
                        if rowStar == maxrow and (remainderRow == -1 or remainderRow > 0):
                            rowStar = rowStardef()
                            colStar = colStar + columnMax + tableColAdd
                            if remainderRow > 0: remainderRow -= 1
                        elif remainderRow == 0 and rowStar == maxrow - 1:
                            rowStar = rowStardef()
                            colStar = colStar + columnMax + tableColAdd
                        else:
                            rowStar += 1
                    else:
                        rowStar += 1
                if "breakdown" in content.keys() and rowStar <= maxrow and zeroFill != "" and \
                        zeroFill != "true" and zeroFill != "0":
                    for colIndex in range(colStar, len(table.columns)):
                        try:
                            tableText = ""
                            for paragraph in table.rows[maxrow].cells[colIndex].paragraphs:
                                tableText += paragraph.text.strip()
                            if tableText == "":
                                table_cell_set(table, maxrow, colIndex, rowStardef(), zeroFill)
                        except Exception as e:
                            pass
                if sumColumn != "" and len(detailValid) > 0:
                    rowIndex += 1
                    if addrow is None and len(table.rows) <= rowStar:
                        break
                    table_cell_set(table, rowStar, colStar, rowStardef(), sumColumn)
                    for indexColumn in range(indexStar, columnMax):
                        if len(tableHeadRemove) > 0 and -1 < indexColumn - indexStar < len(tableHeadRemove) and \
                                tableHeadRemove[indexColumn - indexStar]:
                            continue
                        sumValue = None
                        if len(sumColumnData) > indexColumn: sumValue = sumColumnData[indexColumn]
                        table_cell_set(table, rowStar, colStar + indexColumn + tableColAdd, rowStardef(),
                                       outputFormatData(sumValue, sumColumnName[indexColumn], point,
                                                        indexColumn + tableColAdd, unitsBefore, unitsAfter,
                                                        replaceText, rowIndex))
                    table_setAll_colorBgFont_bold(table, rowStar, content, replaceTable)
                    rowStar += 1
            if "breakdown" in content.keys() and maxrow > 0: rowStar = maxrow + 1
            if addrow is None or (is_number_int(addrow) and int(addrow) != 0):
                if sameRowTableIndex != -1:
                    sameRowTable[sameRowTableIndex][tablePosition] = copy.deepcopy(rowStar)
                    for sameRowTableKey, sameRowTableValue in sameRowTable[sameRowTableIndex].items():
                        if rowStar < sameRowTableValue:
                            rowStar = sameRowTableValue
                for rowDeleteIndex in range(rowStar, len(table.rows)):
                    rowdelete = table.rows[len(table.rows) - 1]
                    table_remove_row(table, rowdelete)
                if rowStar == rowStardef() and slideDelete is not None:
                    for slideDeleteItem in slideDelete:
                        if tablePosition in slideDeleteItem['table_shapes_title']:
                            slideDeleteItem['table_shapes_title'].remove(tablePosition)
                            break
            if mergerStar is not None:
                for ind, mergeritem in enumerate(mergerStar):
                    if str(mergeritem) == "maxrow" or str(mergeritem) == "allrow" or \
                            str(mergeritem).find('allrow') > -1:
                        mergerRowIndexStar, mergerRowIndexEnd, colIndex, equalArray = rowStar - 1, rowStar, [], []
                        if mergeritem == "allrow" or str(mergeritem).find('allrow') > -1:
                            mergerRowIndexStar = rowStardef()
                            if mergeritem != "allrow":
                                colIndex, equalArray = \
                                    mergeritem['allrow']['colIndex'], mergeritem['allrow']['equalArray']
                                if not isinstance(colIndex, list): colIndex = [colIndex]
                                if not isinstance(equalArray, list): equalArray = [equalArray]
                        for mergerRow in range(mergerRowIndexStar, mergerRowIndexEnd):
                            if isinstance(mergerEnd[0], list):
                                for mergerItem in mergerEnd:
                                    table_cell_merger(table, mergeritem, mergerRow, mergerItem, colIndex,
                                                      equalArray, mergerRowSave, mergerColSave)
                            else:
                                table_cell_merger(table, mergeritem, mergerRow, mergerEnd, colIndex, equalArray,
                                                  mergerRowSave, mergerColSave)
                    else:
                        if isinstance(mergeritem[0], list) and isinstance(mergerEnd[0], list):
                            for mergeritemInd, mergeritemStar in enumerate(mergeritem):
                                table_cell_merger(table, '', mergeritemStar, mergerEnd, mergeritemInd, None,
                                                  None, None)
                        else:
                            table_cell_merger(table, '', mergeritem, mergerEnd, ind, None, None, None)
            if mergerColumn is not None:
                for mergerIndex in range(len(mergerColumn)):
                    if len(mergerRowStar[mergerIndex]) > len(mergerRowEnd[mergerIndex]):
                        mergerRowEnd[mergerIndex].append(str(rowStar - 1))
                    if len(mergerRowSave) > 0 and len(mergerColSave) > 0:
                        for mergerColSaveIndex in range(len(mergerColSave)):
                            if int(mergerColSave[mergerColSaveIndex][0]) <= int(columnMerger[mergerIndex]) <= \
                                    int(mergerColSave[mergerColSaveIndex][1]):
                                for rowIndex in range(len(mergerRowStar[mergerIndex])):
                                    if int(mergerRowStar[mergerIndex][rowIndex]) == \
                                            int(mergerRowSave[mergerColSaveIndex]):
                                        mergerRowStar[mergerIndex][rowIndex] = \
                                            int(mergerRowStar[mergerIndex][rowIndex]) + 1
                                    if int(mergerRowEnd[mergerIndex][rowIndex]) == \
                                            int(mergerRowSave[mergerColSaveIndex]):
                                        mergerRowEnd[mergerIndex][rowIndex] = \
                                            int(mergerRowEnd[mergerIndex][rowIndex]) - 1
                    for rowIndex in range(len(mergerRowStar[mergerIndex])):
                        if int(mergerRowStar[mergerIndex][rowIndex]) < int(mergerRowEnd[mergerIndex][rowIndex]) and \
                                rowIndex < len(mergerRowEnd[mergerIndex]) and mergerRowEnd[mergerIndex][rowIndex] != "":
                            if rowStar > int(mergerRowEnd[mergerIndex][rowIndex]) > \
                                    int(mergerRowStar[mergerIndex][rowIndex]):
                                table.cell(int(mergerRowStar[mergerIndex][rowIndex]), int(columnMerger[mergerIndex])) \
                                    .merge(table.cell(int(mergerRowEnd[mergerIndex][rowIndex]),
                                                      int(columnMerger[mergerIndex])))
                                delete_paragraph(table, mergerRowStar[mergerIndex][rowIndex],
                                                 int(columnMerger[mergerIndex]))
                        else:
                            if mergerRowStar[mergerIndex][rowIndex].strip() != "" and \
                                    int(mergerRowStar[mergerIndex][rowIndex]) != int(
                                mergerRowEnd[mergerIndex][rowIndex]) and \
                                    rowStar - 1 > int(mergerRowStar[mergerIndex][rowIndex]):
                                table.cell(int(mergerRowStar[mergerIndex][rowIndex]), int(columnMerger[mergerIndex])) \
                                    .merge(table.cell(rowStar - 1, int(columnMerger[mergerIndex])))
                                delete_paragraph(table, mergerRowStar[mergerIndex][rowIndex],
                                                 int(columnMerger[mergerIndex]))
            if sameRowTableIndex != -1 and zeroFill != "" and zeroFill != "true" and zeroFill != "0":
                zeroFillFlag = True
                for sameRowTableKey, sameRowTableValue in sameRowTable[sameRowTableIndex].items():
                    if sameRowTableValue == 0: zeroFillFlag = False
                if zeroFillFlag:
                    for rowIndex in range(rowStardef(), len(table.rows)):
                        for colIndex in range(colStardef(), len(table.columns)):
                            try:
                                tableText = ""
                                for paragraph in table.rows[rowIndex].cells[colIndex].paragraphs:
                                    tableText += paragraph.text.strip()
                                if tableText == "":
                                    table_cell_set(table, rowIndex, colIndex, rowStardef(), zeroFill)
                            except Exception as e:
                                pass
        except Exception as e:
            print(tablePosition)
            pass
    return None


def regroup_array_by_key(detailValid, group_key, sum_key):
    grouped_dict, detailSaveFlag = {}, False
    for group in detailValid:
        for groupItem in group:
            key_value = groupItem.get(group_key)
            if key_value is None:
                continue  # 或者根据需求抛异常/赋默认值
            if key_value not in grouped_dict:
                grouped_dict[key_value] = []
            if 'text' in groupItem.keys() and str(groupItem['text']).find('保留】') > -1:
                detailSaveFlag = True
            grouped_dict[key_value].append(groupItem)
    # 返回的是一个二维数组，每个子列表是相同 key 值的 JSON 列表
    detailValidGroup, detailValidGroupNew = list(grouped_dict.values()), []
    for detailValidGroupIndex, detailValidGroupItem in enumerate(detailValidGroup):
        detailValidGroupNew.append([])
        for detailValidGroupItemData in detailValidGroupItem:
            if 'text' in detailValidGroupItemData.keys() and str(detailValidGroupItemData['text']) == sum_key:
                if len(detailValidGroupNew[len(detailValidGroupNew) - 1]) == 0:
                    detailValidGroupNew[len(detailValidGroupNew) - 1].append(detailValidGroupItemData)
                    detailValidGroupNew.append([])
                else:
                    detailValidGroupNew.append([])
                    detailValidGroupNew[len(detailValidGroupNew) - 1].append(detailValidGroupItemData)
            else:
                detailValidGroupNew[len(detailValidGroupNew) - 1].append(detailValidGroupItemData)
    return detailValidGroupNew, detailSaveFlag


def table_cell_merger(table, mergerFlag, mergerRow, mergerCol, colIndex, equalArray, mergerRowSave, mergerColSave):
    try:
        if str(mergerFlag) == "maxrow" or str(mergerFlag) == "allrow" or str(mergerFlag).find('allrow') > -1:
            mergerRowFlag, colIndexSave = True, 0
            if len(colIndex) > 0 and len(colIndex) == len(equalArray):
                for colIndexInd, colIndexItem in enumerate(colIndex):
                    if int(mergerCol[0]) <= int(colIndexItem) <= int(mergerCol[1]):
                        equalText, colIndexSave = '', int(colIndexItem)
                        for paragraph in table.rows[mergerRow].cells[int(colIndexItem)].paragraphs:
                            equalText += paragraph.text.strip()
                        if equalText.strip() != equalArray[colIndexInd].strip():
                            mergerRowFlag = False
            if int(mergerCol[0]) < len(table.columns) and \
                    int(mergerCol[1]) < len(table.columns) and mergerRowFlag:
                mergerText = [""] * (int(mergerCol[1]) - int(mergerCol[0]) + 1)
                for mergerTextIndex in range((int(mergerCol[1]) - int(mergerCol[0]) + 1)):
                    mergerColIndex = int(mergerCol[0]) + mergerTextIndex
                    for paragraph in table.rows[mergerRow].cells[mergerColIndex].paragraphs:
                        mergerText[mergerTextIndex] += paragraph.text.strip()
                if mergerText.count("") < len(mergerText) - 1:
                    if str(mergerFlag) == "maxrow":
                        for mergerColIndex in range(int(mergerCol[0]) + 1, int(mergerCol[1]) + 1):
                            table_cell_set(table, mergerRow, mergerColIndex, mergerRow, "")
                    if str(mergerFlag) != "allrow" and str(mergerFlag).find('allrow') > -1:
                        for mergerColIndex in range(int(mergerCol[0]), int(mergerCol[1]) + 1):
                            if mergerColIndex != colIndexSave:
                                if mergerRow + 1 < len(table.rows) and \
                                    table.rows[mergerRow + 1].cells[mergerColIndex].paragraphs[0].text.strip() == '' \
                                        and table.rows[mergerRow].cells[mergerColIndex].paragraphs[0].text.strip() != '':
                                    table_cell_set(table, mergerRow + 1, mergerColIndex, mergerRow,
                                                   table.rows[mergerRow].cells[mergerColIndex].paragraphs[0].text)
                                table_cell_set(table, mergerRow, mergerColIndex, mergerRow, "")
                table.cell(mergerRow, int(mergerCol[0])).merge(table.cell(mergerRow, int(mergerCol[1])))
                delete_paragraph(table, mergerRow, int(mergerCol[0]))
                if len(colIndex) > 0 and len(colIndex) == len(equalArray):
                    mergerRowSave.append(mergerRow), mergerColSave.append(mergerCol)
        else:
            if colIndex < len(mergerCol) and int(mergerRow[0]) < len(table.rows) and \
                    int(mergerCol[colIndex][0]) < len(table.rows) and \
                    int(mergerRow[1]) < len(table.columns) and int(mergerCol[colIndex][1]) < len(table.columns):
                if int(mergerRow[0]) == int(mergerCol[colIndex][0]):
                    for mergerColIndex in range(int(mergerRow[1]) + 1, int(mergerCol[colIndex][1]) + 1):
                        if table.rows[int(mergerRow[0])].cells[int(mergerRow[1])].paragraphs[0].text == \
                                table.rows[int(mergerRow[0])].cells[mergerColIndex].paragraphs[0].text:
                            table_cell_set(table, int(mergerRow[0]), mergerColIndex, int(mergerRow[0]), "")
                table.cell(int(mergerRow[0]), int(mergerRow[1])). \
                    merge(table.cell(int(mergerCol[colIndex][0]), int(mergerCol[colIndex][1])))
                delete_paragraph(table, int(mergerRow[0]), int(mergerRow[1]))
    except Exception as e:
        pass


def table_remove_row(table, row):
    try:
        tbl = table._tbl
        tr = row._tr
        tbl.remove(tr)
    except Exception as e:
        pass


def delete_paragraph(table, rowStar, columnIndex):
    try:
        for paragraph in table.cell(int(rowStar), columnIndex).text_frame.paragraphs:
            if str(paragraph.text) == "":
                p = paragraph._element
                p.getparent().remove(p)
                # p._p = p._element = None
                paragraph._p = paragraph._element = None
    except Exception as e:
        pass


def alignment_paragraph(table, rowStar, columnIndex):
    try:
        for paragraph in table.rows[int(rowStar)].cells[columnIndex].paragraphs:
            if str(paragraph.text) != "":
                paragraph.alignment = PP_ALIGN.CENTER
    except Exception as e:
        pass


def table_cell_set(table, rowIndex, columnIndex, firstRow, contect, fromContect=None):
    try:
        firstRowHeight = table.rows[firstRow]
        table.rows[rowIndex].height = firstRowHeight.height
        #firstRowColumn = table.cell(firstRow, columnIndex)
        #table.cell(rowIndex, columnIndex).vertical_anchor = firstRowColumn.vertical_anchor
        paragraphs = table.cell(rowIndex, columnIndex).text_frame.paragraphs
        runList, runText, runFlag, runListFlag = [], "", False, False,
        for paragraph in paragraphs:
            if fromContect is not None:
                fromtextFirst, fromtextLast = fromContect[0], fromContect[len(fromContect) - 1]
                if str(paragraph.text).find(fromContect) > -1:
                    for runIndex, runItem in enumerate(paragraph.runs):
                        if runItem.text.find(fromtextFirst) > -1 or runFlag:
                            if runItem.text.find(fromtextLast) > -1:
                                runList.append(runIndex)
                                runText += runItem.text
                                runTextBefore = ""
                                runTextAfter = ""
                                if runText.find(fromContect) > -1:
                                    if runText != fromContect:
                                        if runText.find(fromContect) == 0:
                                            runTextAfter = runText.replace(fromContect, "")
                                        else:
                                            runTextRetain = runText.split(fromContect)
                                            runTextBefore = runTextRetain[0]
                                            if len(runTextRetain) > 1: runTextAfter = runTextRetain[1]
                                            if len(runTextRetain) > 2: runTextAfter += contect + runTextRetain[2]
                                            if len(runTextRetain) > 3: runTextAfter += contect + runTextRetain[3]
                                    for runListItem in runList:
                                        paragraph.runs[runListItem].text = ""
                                    if contect.find('“') > -1 and contect.find('”') > -1:
                                        if runList[0] > 0 and runList[len(runList) - 1] < len(paragraph.runs) - 1:
                                            if paragraph.runs[runList[0] - 1].text.find('“') > -1 and \
                                                    paragraph.runs[runList[len(runList) - 1] + 1].text.find('”') == 0:
                                                runTextBefore = paragraph.runs[runList[0] - 1].\
                                                                    text.replace('“','') + runTextBefore
                                                paragraph.runs[runList[len(runList) - 1] + 1].text = \
                                                    paragraph.runs[runList[len(runList) - 1] + 1].text.replace('”', '')
                                                for runListIndex, runListItem in enumerate(runList):
                                                    runList[runListIndex] = runListItem - 1
                                    if len(runList) == 1:
                                        paragraph.runs[runList[0]].text = runTextBefore + contect + runTextAfter
                                    else:
                                        if runTextBefore != "":
                                            paragraph.runs[runList[0]].text = runTextBefore + contect
                                        else:
                                            paragraph.runs[runList[0]].text = contect
                                        paragraph.runs[runList[len(runList) - 1]].text = runTextAfter
                                    return True
                                else:
                                    if runItem.text.find(fromtextFirst) > -1 and runItem.text.find(fromtextLast) > -1:
                                        runList, runText, runFlag = [], "", False
                                    elif runItem.text.find(fromtextFirst) > -1:
                                        runList = [runIndex]
                                        runText = runItem.text
                                        runFlag = True
                                    else:
                                        runList, runText, runFlag = [], "", False
                            else:
                                runList.append(runIndex)
                                runText += runItem.text
                                runFlag = True
            else:
                for runIndex, runItem in enumerate(paragraph.runs):
                    if runIndex == 0:
                        runItem.text = contect
                    else:
                        runItem.text = ''
    except Exception as e:
        pass


def table_setAll_colorBgFont_bold(table, rowStar, content, replaceTable):
    colorColStardef = lambda: 0 if "colorColStar" not in content.keys() else content["colorColStar"]
    colorColEnddef = lambda: -1 if "colorColEnd" not in content.keys() else content["colorColEnd"]
    parityLinedef = lambda: "" if "parityLine" not in content.keys() else content["parityLine"]
    colorColIndexdef = lambda: 0 if "colorColIndex" not in content.keys() else content["colorColIndex"]
    colorBgdef = lambda: "" if "colorBg" not in content.keys() else content["colorBg"]
    colorFontdef = lambda: "" if "colorFont" not in content.keys() else content["colorFont"]
    totalitydef = lambda: "" if "totality" not in content.keys() else content["totality"]
    equalArraydef = lambda: "" if "equalArray" not in content.keys() else content["equalArray"]
    bolddef = lambda: "" if "bold" not in content.keys() else content["bold"]
    colorColStar, parityLine, colorColIndex, totality, colorBg, colorFont, equalArray, colorColEnd, bold = \
        colorColStardef(), parityLinedef(), colorColIndexdef(), totalitydef(), colorBgdef(), colorFontdef(), \
        equalArraydef(), colorColEnddef(), bolddef()
    if isinstance(colorColStar, dict):
        for keyColStar, valueColStar in colorColStar.items():
            if keyColStar == "colorBg" and isinstance(parityLine, str) and parityLine != "":
                tabBgColor(table, rowStar, colorColStar, colorColEnd, colorBg, parityLine,
                           colorColIndex, totality)
            else:
                for valueColStarIndex, valueColStarItem in enumerate(valueColStar):
                    if keyColStar in colorColEnd and isinstance(colorColEnd[keyColStar], list) and \
                            str(colorColEnd[keyColStar][valueColStarIndex]).strip() != "":
                        colorColEndItem = int(str(colorColEnd[keyColStar][valueColStarIndex]).strip())
                    else:
                        colorColEndItem = len(table.columns)
                    if keyColStar in colorColIndex and isinstance(colorColIndex[keyColStar], list) and \
                            str(colorColIndex[keyColStar][valueColStarIndex]).strip() != "":
                        colorColIndexItem = str(colorColIndex[keyColStar][valueColStarIndex]).strip()
                    else:
                        colorColIndexItem = ""
                    if keyColStar in equalArray and isinstance(equalArray[keyColStar], list):
                        if isinstance(equalArray[keyColStar][valueColStarIndex], list) and \
                                len(equalArray[keyColStar][valueColStarIndex]) > 0:
                            equalArrayItem = equalArray[keyColStar][valueColStarIndex]
                            if replaceTable is not None:
                                if isinstance(replaceTable, list):
                                    replaceFrom = replaceTable[0]
                                    replaceTo = replaceTable[1]
                                    for replaceIndex, replaceItem in enumerate(replaceFrom):
                                        if isinstance(equalArrayItem, list):
                                            for equalArrayItemIndex, equalArrayItemText in enumerate(equalArrayItem):
                                                if equalArrayItemText.strip() == str(replaceItem).strip() and \
                                                        replaceIndex < len(replaceTo):
                                                    if replaceTo[replaceIndex] is not None:
                                                        equalArrayItem[equalArrayItemIndex] = replaceTo[replaceIndex]
                                        elif isinstance(equalArrayItem, str):
                                            if equalArrayItem.strip() == str(replaceItem).strip() and \
                                                    replaceIndex < len(replaceTo):
                                                if replaceTo[replaceIndex] is not None:
                                                    equalArrayItem = replaceTo[replaceIndex]
                        else:
                            equalArrayItem = ""
                    else:
                        equalArrayItem = ""
                    if keyColStar in colorFont and isinstance(colorFont[keyColStar], list):
                        colorFontItem = colorFont[keyColStar][valueColStarIndex]
                    else:
                        colorFontItem = ""
                    if keyColStar in parityLine and isinstance(parityLine[keyColStar], list):
                        parityLineItem = parityLine[keyColStar][valueColStarIndex]
                    else:
                        parityLineItem = ""
                    if parityLineItem != '':
                        tabBgColor(table, rowStar, valueColStarItem, colorColEndItem, colorFontItem,
                                   parityLineItem, colorColIndexItem, totality)
                    else:
                        table_font_color_bold(table, rowStar, valueColStarItem, colorColEndItem,
                                              colorColIndexItem, equalArrayItem, colorFontItem,
                                              keyColStar)
    else:
        if colorColEnd == -1: colorColEnd = len(table.columns)
        if isinstance(colorBg, list):
            for colorBgIndex, colorBgItem in enumerate(colorBg):
                if str(colorBgItem).strip() != "":
                    if isinstance(colorColStar, list):
                        if colorBgIndex < len(colorColStar):
                            colorColStarItem = colorColStar[colorBgIndex]
                        else:
                            colorColStarItem = colorColStar[0]
                    else:
                        colorColStarItem = colorColStar
                    if isinstance(parityLine, list):
                        if colorBgIndex < len(parityLine):
                            parityLineItem = parityLine[colorBgIndex]
                        else:
                            parityLineItem = parityLine[0]
                    else:
                        parityLineItem = parityLine
                    if isinstance(colorColIndex, list):
                        if colorBgIndex < len(colorColIndex):
                            colorColIndexItem = colorColIndex[colorBgIndex]
                        else:
                            colorColIndexItem = colorColIndex[0]
                    else:
                        colorColIndexItem = colorColIndex
                    if isinstance(totality, list):
                        if colorBgIndex < len(totality):
                            totalityItem = totality[colorBgIndex]
                        else:
                            totalityItem = totality[0]
                    else:
                        totalityItem = totality
                    tabBgColor(table, rowStar, colorColStarItem, colorColEnd, colorBgItem, parityLineItem,
                               colorColIndexItem, totalityItem)
        else:
            if str(colorBg).strip() != "":
                tabBgColor(table, rowStar, colorColStar, colorColEnd, colorBg, parityLine, colorColIndex,
                           totality)
        if isinstance(bold, list) or (isinstance(bold, str) and bold.strip() != "") or \
                isinstance(colorFont, list):
            if isinstance(colorColStar, list):
                font_paragraph(table, rowStar, bold, colorFont, colorColStar[0], colorColEnd,
                               colorColIndex, equalArray)
            else:
                font_paragraph(table, rowStar, bold, colorFont, colorColStar, colorColEnd,
                               colorColIndex, equalArray)


def table_font_color_bold(table, rowIndex, colStar, cols, colLine, equalArray, colorStr, flag):
    try:
        if is_number(colLine) and colLine != "": colLine = int(colLine)
        shading_list = locals()
        if isinstance(equalArray, list) and len(equalArray) == 1 and str(equalArray[0]) == '':equalArray = ''
        if equalArray == "":
            for colIndex in range(int(colStar), cols + 1):
                if flag == "colorFont" or flag == "bold":
                    paragraphs = table.cell(rowIndex, colIndex).text_frame.paragraphs
                    for paragraph in paragraphs:
                        for run in paragraph.runs:
                            if flag == "bold":
                                run.font.bold = True
                            else:
                                run.font.color.rgb = RGBColor(int(colorStr[0]), int(colorStr[1]), int(colorStr[2]))
                else:
                    color_rgb = list(hex_to_rgb(colorStr))
                    table.cell(rowIndex, colIndex).fill.solid()
                    table.cell(rowIndex, colIndex).fill.fore_color.rgb = \
                        RGBColor(color_rgb[0], color_rgb[1], color_rgb[2])
        else:
            tableText = ""
            if isinstance(colLine, int):
                for paragraph in table.cell(rowIndex, colLine).text_frame.paragraphs:
                    tableText += paragraph.text.strip()
            for colIndex in range(int(colStar), cols + 1):
                if tableText == "":
                    for paragraph in table.cell(rowIndex, colLine).text_frame.paragraphs:
                        tableText += paragraph.text.strip()
                if tableText in equalArray:
                    if flag == "colorFont" or flag == "bold":
                        paragraphs = table.cell(rowIndex, colIndex).text_frame.paragraphs
                        for paragraph in paragraphs:
                            for run in paragraph.runs:
                                if flag == "bold":
                                    run.font.bold = True
                                else:
                                    run.font.color.rgb = RGBColor(int(colorStr[0]), int(colorStr[1]), int(colorStr[2]))
                    else:
                        color_rgb = list(hex_to_rgb(colorStr))
                        table.cell(rowIndex, colIndex).fill.solid()
                        table.cell(rowIndex, colIndex).fill.fore_color.rgb = \
                            RGBColor(color_rgb[0], color_rgb[1], color_rgb[2])
    except Exception as e:
        pass


def hex_to_rgb(colorStr):
    value = colorStr.lstrip('#')
    lv = len(value)
    return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))


def font_paragraph(table, rowIndex, bold, colorStr, colStar, cols, colLine, equalArray):
    try:
        if is_number(colLine):colLine = int(colLine)
        if isinstance(bold, list) or (isinstance(bold, str) and bold != ""):
            if isinstance(bold, list):
                if isinstance(bold[0], list):
                    tableText, boldFlag = "", False
                    for paragraph in table.cell(rowIndex, colLine).text_frame.paragraphs:
                        tableText += paragraph.text.strip()
                    if tableText in bold[0]:
                        boldFlag = True
                    if boldFlag:
                        for colIndex in bold[1]:
                            if colIndex < cols:
                                paragraphs = table.cell(rowIndex, int(colIndex)).text_frame.paragraphs
                                for paragraph in paragraphs:
                                    for run in paragraph.runs:
                                        run.font.bold = True
                else:
                    for boldItem in bold:
                        paragraphs = table.cell(rowIndex, int(boldItem)).text_frame.paragraphs
                        for paragraph in paragraphs:
                            for run in paragraph.runs:
                                run.font.bold = True
            else:
                if int(bold) < cols:
                    paragraphs = table.cell(rowIndex, int(bold)).text_frame.paragraphs
                    for paragraph in paragraphs:
                        for run in paragraph.runs:
                            run.font.bold = True
        if isinstance(colorStr, list):
            if isinstance(colorStr[0], list):
                for colIndex in range(int(colStar), cols):
                    for colorIndex, colorItem in enumerate(colorStr):
                        if str(table.cell(rowIndex, colIndex).text).strip() in equalArray[colorIndex]:
                            paragraphs = table.cell(rowIndex, colIndex).text_frame.paragraphs
                            for paragraph in paragraphs:
                                for run in paragraph.runs:
                                    run.font.color.rgb = RGBColor(colorItem[0],colorItem[1],colorItem[2])
            else:
                if str(table.cell(rowIndex, colLine).text).strip() in equalArray:
                    if colStar != "":
                        for colIndex in range(int(colStar), cols):
                            paragraphs = table.cell(rowIndex, colIndex).text_frame.paragraphs
                            for paragraph in paragraphs:
                                for run in paragraph.runs:
                                    run.font.color.rgb = RGBColor(colorStr[0],colorStr[1],colorStr[2])
                    else:
                        paragraphs = table.cell(rowIndex, colLine).text_frame.paragraphs
                        for paragraph in paragraphs:
                            for run in paragraph.runs:
                                run.font.color.rgb = RGBColor(colorStr[0], colorStr[1], colorStr[2])
    except Exception as e:
        pass


def tabBgColor(table, rowIndex, colStar, cols, colorStr, parityLine, colLine, totality):
    try:
        shading_list = locals()
        if is_number(colLine): colLine = int(colLine)
        for colIndex in range(int(colStar), cols + 1):
            if parityLine == "":
                if str(totality).strip() != "":
                    tableText = ""
                    for paragraph in table.cell(rowIndex, colLine).text_frame.paragraphs:
                        tableText += paragraph.text.strip()
                    if tableText == str(totality).strip():
                        color_rgb = list(hex_to_rgb(colorStr))
                        table.cell(rowIndex, colIndex).fill.solid()
                        table.cell(rowIndex, colIndex).fill.fore_color.rgb = \
                            RGBColor(color_rgb[0], color_rgb[1], color_rgb[2])
                else:
                    color_rgb = list(hex_to_rgb(colorStr))
                    table.cell(rowIndex, colIndex).fill.solid()
                    table.cell(rowIndex, colIndex).fill.fore_color.rgb = \
                        RGBColor(color_rgb[0], color_rgb[1], color_rgb[2])
            else:
                parityLineInt = int(parityLine)
                if (rowIndex + parityLineInt) % 2 == 0:
                    color_rgb = list(hex_to_rgb(colorStr))
                    table.cell(rowIndex, colIndex).fill.solid()
                    table.cell(rowIndex, colIndex).fill.fore_color.rgb = \
                        RGBColor(color_rgb[0], color_rgb[1], color_rgb[2])
    except Exception as e:
        pass


def deleteSlide(pptx_path, slideDelete):
    try:
        if slideDelete is not None:
            documentPptx = Presentation(pptx_path)
            slidesCount = len(documentPptx.slides)
            for slideIndex in range(slidesCount - 1, -1, -1):
                if slideIndex < len(slideDelete):
                    if slideDelete[slideIndex]['text_shapes_count'] == 0 and \
                        slideDelete[slideIndex]['chart_shapes_count'] == 0 and \
                        slideDelete[slideIndex]['table_shapes_count'] == 0:
                        slideDeleteFlag = False
                    else:
                        slideDeleteFlag = True
                    if slideDeleteFlag:
                        if (slideDelete[slideIndex]['text_shapes_count'] > 0 and
                                len(slideDelete[slideIndex]['text_shapes_title']) > 0) or \
                                (slideDelete[slideIndex]['chart_shapes_count'] > 0 and
                                len(slideDelete[slideIndex]['chart_shapes_title']) > 0) or \
                                (slideDelete[slideIndex]['table_shapes_count'] > 0 and
                                len(slideDelete[slideIndex]['table_shapes_title']) > 0):
                            slideDeleteFlag = False
                    if slideDeleteFlag:
                        xml_slides = documentPptx.slides._sldIdLst
                        slides = list(xml_slides)
                        xml_slides.remove(slides[slideIndex])
            documentPptx.save(pptx_path)
    except Exception as e:
        pass


def is_fromData(columnString):
    if columnString.find("data") > -1:
        if columnString.find(":") > -1 or columnString.find("+") > -1 or \
            columnString.find("-") > -1 or columnString.find("*") > -1  or columnString.find("/") > -1:
            return True
        else:
            return False
    else:
        if is_number(columnString):
            return True
        else:
            return False


def passRate(passString, json_data):
    division = passString.split('/')
    molecules,moleculesCount,moleculesDataIndex = division[0].split(','),0,0
    denominator,denominatorCount,denominatorDataIndex = division[1].split(','),0,0
    for moleculesIndex, moleculesItem in enumerate(molecules):
        datasource = json.loads(json_data[moleculesItem])
        if moleculesIndex == 0:
            moleculesCount = len(datasource["detailValid"])
        else:
            if moleculesCount > len(datasource["detailValid"]):
                moleculesCount = len(datasource["detailValid"])
                moleculesDataIndex = moleculesIndex
    for denominatorIndex, denominatorItem in enumerate(denominator):
        datasource = json.loads(json_data[denominatorItem])
        if denominatorIndex == 0:
            denominatorCount = len(datasource["detailValid"])
        else:
            if denominatorCount > len(datasource["detailValid"]):
                denominatorCount = len(datasource["detailValid"])
                denominatorDataIndex = denominatorIndex
    datasource = json.loads(json_data[molecules[moleculesDataIndex]])
    moleculesData = copy.deepcopy(datasource["detailValid"])
    datasource = json.loads(json_data[denominator[denominatorDataIndex]])
    denominatorData = copy.deepcopy(datasource["detailValid"])
    for moleculesIndex, moleculesItem in enumerate(molecules):
        if moleculesIndex != moleculesDataIndex:
            datasource = json.loads(json_data[molecules[moleculesIndex]])
            for dataItem in moleculesData:
                dataFlag = False
                for detailValidItem in datasource["detailValid"]:
                    if dataItem['text'] == detailValidItem['text']:
                        dataFlag = True
                        break
                if not dataFlag:
                    moleculesCount -= 1
    for denominatorIndex, denominatorItem in enumerate(denominator):
        if denominatorIndex != denominatorDataIndex:
            datasource = json.loads(json_data[denominator[denominatorIndex]])
            for dataItem in denominatorData:
                dataFlag = False
                for detailValidItem in datasource["detailValid"]:
                    if dataItem['text'] == detailValidItem['text']:
                        dataFlag = True
                        break
                if not dataFlag:
                    denominatorCount -= 1
    if denominatorCount == 0:
        return 0
    else:
        return (moleculesCount / denominatorCount) * 100


def returnPercentileRank(averageString, detailValid):
    average = float(averageString)
    moleculesCount, denominatorCount = 0, len(detailValid)
    detailValid.sort(key=lambda x: x["average"], reverse=False)
    for detailValidItem in detailValid:
        if detailValidItem['average'] <= average:
            moleculesCount += 1
        else:
            break
    if denominatorCount < 10:
        return None
    else:
        return moleculesCount / denominatorCount


def formatdata(_data: float, _len: int, _type = None) -> object:
    formatstr, _len = '{:.2f}', int(_len)
    if _len == 0:
        text = Decimal(str(_data)).quantize(Decimal('1.'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.0f}'
    elif _len == 1:
        text = Decimal(str(_data)).quantize(Decimal('0.1'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.1f}'
    elif _len == 2:
        text = Decimal(str(_data)).quantize(Decimal('0.01'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.2f}'
    elif _len == 3:
        text = Decimal(str(_data)).quantize(Decimal('0.001'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.3f}'
    elif _len == 4:
        text = Decimal(str(_data)).quantize(Decimal('0.0001'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.4f}'
    elif _len == 5:
        text = Decimal(str(_data)).quantize(Decimal('0.00001'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.5f}'
    elif _len == 6:
        text = Decimal(str(_data)).quantize(Decimal('0.000001'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.6f}'
    elif _len == 7:
        text = Decimal(str(_data)).quantize(Decimal('0.0000001'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.7f}'
    elif _len == 8:
        text = Decimal(str(_data)).quantize(Decimal('0.00000001'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.8f}'
    elif _len == 9:
        text = Decimal(str(_data)).quantize(Decimal('0.000000001'), rounding = "ROUND_HALF_UP")
        formatstr = '{:.9f}'
    else:
        text = Decimal(str(_data)).quantize(Decimal('1.'), rounding = "ROUND_HALF_UP")
    if _type is None:
        if _len == 0:
            text = str(round(text))
        else:
            text = formatstr.format(float(text))
    elif _type == "c":
        if _len == 0:
            text = round(text)
        else:
            text = float(text)
    else:
        if _len == 0:
            text = str(round(text))
        else:
            text = str(text)
    return text


def formatchart(_units, _point):
    if _units=="":
        text=json.dumps(dict(format="%." + str(_point) + "f"))
    else:
        formatstring = ["per", "%." + str(_point) + "f"]
        text=json.dumps(dict(format=formatstring))
    return json.loads(text)


def returncount(dataList, topN, column, pointStr):
    point = 2
    if isinstance(pointStr, str) and pointStr != "":point = int(pointStr)
    if isinstance(pointStr, int):point = pointStr
    if column == "validpercent" or column == "casepercent" or column == "passRate" or column == "masteryRate" or \
            column == "percentileRank":
        point += 2
    if topN >= len(dataList):
        return len(dataList)
    else:
        if float(str(formatdata(sort_key(dataList[topN - 1][column], None), point))) != \
                float(str(formatdata(sort_key(dataList[topN][column], None), point))):
            if column == "validpercent" and topN > 2:
                countFlag = True
                for topNIndex in range(topN - 1):
                    if float(str(formatdata(dataList[topNIndex][column], point))) != 1.0:
                        countFlag = False
                        break
                if float(str(formatdata(dataList[topN - 1][column], point))) == 1.0:
                    countFlag = False
                if countFlag:
                    topN -= 1
            if (column == "casepercent" or column == "validpercent" or column == "average") and topN > 1:
                while topN > 1:
                    countFlag = True
                    if column == "validpercent":
                        if abs(dataList[topN - 2][column] - dataList[topN - 1][column]) < 0.19:
                            countFlag = False
                    elif column == "average":
                        for dataListItem in dataList:
                            if dataListItem[column] < 0 or dataListItem[column] > 5:
                                countFlag = False
                        if abs(dataList[topN - 2][column] - dataList[topN - 1][column]) < 1.5:
                            countFlag = False
                    else:
                        if abs(dataList[topN - 2][column] - dataList[topN - 1][column]) < 0.09:
                            countFlag = False
                        if topN > 2 and abs(dataList[topN - 3][column] - dataList[topN - 2][column]) > 0.03:
                            countFlag = False
                    if countFlag:
                        topN -= 1
                    else:
                        # 条件不满足，保持当前 topN 值并退出循环
                        break
            return topN
        else:
            if topN <= 2:
                topN+=1
                for num in range(topN - 1, len(dataList) - 1):
                    if float(str(formatdata(sort_key(dataList[num][column], None), point))) == \
                            float(str(formatdata(sort_key(dataList[num + 1][column], None), point))):
                        topN+=1
                    else:
                        break
            else:
                if float(str(formatdata(sort_key(dataList[topN - 2][column], None), point))) != \
                        float(str(formatdata(dataList[topN - 1][column], point))):
                    topN-=1
                else:
                    topN+=1
                    for num in range(topN - 1, len(dataList) - 1):
                        if float(str(formatdata(sort_key(dataList[num][column], None), point))) == \
                                float(str(formatdata(sort_key(dataList[num + 1][column], None), point))):
                            topN+=1
                        else:
                            break
            return topN


def returncountRepeat(dataList, topN, column, pointStr):
    point,dataRepeat = 2, []
    if isinstance(pointStr, str) and pointStr != "":point = int(pointStr)
    if isinstance(pointStr, int):point = pointStr
    if column == "validpercent" or column == "casepercent" or column == "passRate" or column == "masteryRate" or \
            column == "percentileRank":
        point += 2
    if topN >= len(dataList):
        return len(dataList)
    else:
        for index in range(topN):
            if float(str(formatdata(sort_key(dataList[index][column], None), point))) not in dataRepeat:
                dataRepeat.append(float(str(formatdata(sort_key(dataList[index][column], None), point))))
        if topN != len(dataRepeat):
            topRepeat = topN
            for index in range(topRepeat, len(dataList)):
                if float(str(formatdata(sort_key(dataList[index][column], None), point))) not in dataRepeat:
                    dataRepeat.append(float(str(formatdata(sort_key(dataList[index][column], None), point))))
                    topN += 1
                    if topRepeat == len(dataRepeat):
                        break
                else:
                    topN += 1
        topRepeat = topN
        for index in range(topRepeat, len(dataList)):
            if float(str(formatdata(sort_key(dataList[index - 1][column], None), point))) == \
                    float(str(formatdata(sort_key(dataList[index][column], None), point))):
                topN += 1
            else:
                break
    return topN


def topk_partition(dataList, topN, column, point):
    """
    输出matrix矩阵的最大/小前k个值的index，无序
    所对应的top k的值：matrix[index[i][0], index[i][1]]
                        matrix[index[i]]
    :param dataList:
    :param topN:
    :param column:
    :param point:
    :return:
    """
    matrix,top_max = [], True
    if dataList[0][column] < dataList[len(dataList)][column]:
        top_max = False
    for num in range(len(dataList)):
        matrix.append(float(str(formatdata(dataList[num][column], point))))
    matrix = np.array(matrix)
    flag_2d = False
    if len(matrix.shape) == 2:
        flag_2d = True
        matrix1 = matrix.reshape((matrix.shape[0] * matrix.shape[1]))
    else:
        matrix1 = matrix.copy()
    if top_max:  # matrix前k个最大值 所对应的index
        index = np.argpartition(matrix1, -topN)[-topN:len(matrix1)]
    else:  # matrix前k个最小值 所对应的index
        index = np.argpartition(matrix1, topN - 1)[0:topN]

    # 解析index
    if flag_2d:
        index_2d = []
        for num in index:
            rowIndex = num // matrix.shape[1]
            col = num % matrix.shape[1]
            index_2d.append([rowIndex, col])
        index = index_2d

    return index


def replacetext(text, replaceText):
    replaceString = ["、、", "，，", "；；", "。。", "、，", "，；", "、；", "，。", "；。", "。，", "。；", "。、", "、。"]
    newString = ["、", "，", "；", "。", "，", "；", "；", "。", "。", "。", "。", "。", "。"]
    num_dict = ['零', '一', '两', '三', '四', '五', '六', '七', '八', '九']
    for replaceIndex in range(20):
        for j in range(len(replaceString)):
            if text.find(replaceString[j]) > -1:
                text = str(text).replace(replaceString[j], newString[j])
    if isinstance(replaceText, list):
        replaceFrom = replaceText[0]
        replaceTo = replaceText[1]
        for replaceIndex, replaceItem in enumerate(replaceFrom):
            if text.find(str(replaceItem).strip()) > -1 and replaceIndex < len(replaceTo):
                text = str(text).replace(str(replaceItem).strip(), replaceTo[replaceIndex])
            else:
                if str(replaceItem).strip() == ".XX" and replaceIndex < len(replaceTo) and \
                        is_number(text.replace("%", "")):
                    if text.find("%") > -1:
                        if replaceTo[replaceIndex] == "":
                            text = str(int(float(text.replace("%", "")))) + "%"
                        else:
                            text = num_dict[int(float(text.replace("%", "")) / 10)] + replaceTo[replaceIndex]
                    else:
                        text = str(int(float(text)))
    return text


def is_number(s):
    try:  # 如果能运行float(s)语句，返回True（字符串s是浮点数）
        if isinstance(s, list):
            return False
        else:
            float(s)
            return True
    except ValueError:  # ValueError为Python的一种标准异常，表示"传入无效的参数"
        pass  # 如果引发了ValueError这种异常，不做任何事情（pass：不做任何事情，一般用做占位语句）
    try:
        import unicodedata  # 处理ASCii码的包
        for n in s:
            unicodedata.numeric(n)  # 把一个表示数字的字符串转换为浮点数返回的函数
            #return True
        return True
    except (TypeError, ValueError):
        pass
    return False


def sort_key(s, flag):
    # 排序关键字匹配
    # 匹配开头数字序号
    if isinstance(s, str) and not is_number(s) and s != 'None':
        try:
            if not (s.find("10月") > -1 or s.find("11月") > -1 or s.find("12月") > -1):
                replaceOld = ["1月","2月","3月","4月","5月","6月","7月","8月","9月"]
                replaceNew = ["01月", "02月", "03月", "04月", "05月", "06月", "07月", "08月", "09月"]
                for replaceIndex, replaceItem in enumerate(replaceOld):
                    s = s.replace(replaceItem, replaceNew[replaceIndex])
            if s.find("月1日") > -1 or s.find("月2日") > -1 or s.find("月3日") > -1 or s.find("月4日") > -1 or \
                    s.find("月5日") > -1 or s.find("月6日") > -1 or s.find("月7日") > -1 or s.find("月8日") > -1 or \
                    s.find("月9日") > -1:
                replaceOld = ["1日", "2日", "3日", "4日", "5日", "6日", "7日", "8日", "9日"]
                replaceNew = ["01日", "02日", "03日", "04日", "05日", "06日", "07日", "08日", "09日"]
                for replaceIndex, replaceItem in enumerate(replaceOld):
                    s = s.replace(replaceItem, replaceNew[replaceIndex])
            if s.find("年") > -1 and (s.find("月") > -1 or s.find("日") > -1):
                c = float("".join(list(filter(str.isdigit, s))))
                return c
            else:
                return s
        except:
            return s
    elif isinstance(s, list) and len(s) > 0:
        return s[0]
    else:
        if s is None or s == "None" or s == '':
            if flag is None:
                return 0
            else:
                if flag:
                    return -999999999
                else:
                    return 999999999
        elif is_number(s) and isinstance(s, str):
            return float(s)
        else:
            return s


def myDataSetId(PlatID, ProjID, mongodb_cfg, analysis, dataSetIdFlag, caseCondition=None):
    analysisThreadFlag, dataSetIdFlag['frequency'], frequencyIndex, meansIndex, crosstabsIndex, comparemeansIndex = \
        True, [[],[],[],[]], 0, 0, 0, 0
    multipleIndex, crosstabsMultipleIndex = 0, 0
    dataSetIdFlag['means'] = [[],[],[],[]]
    dataSetIdFlag['crosstabs'] = [[], [], [], []]
    dataSetIdFlag['comparemeans'] = [[], [], [], []]
    dataSetIdFlag['multiple'] = [[], [], [], []]
    dataSetIdFlag['crosstabsMultiple'] = [[], [], [], []]
    dataSetIdFlag['dataSetId'] = {}
    dataSetIdFlag['version'] = {}
    dataSetIdFlag['myAnalysisFrequency'] = False
    dataSetIdFlag['myAnalysisMeans'] = False
    dataSetIdFlag['myAnalysisMultiple'] = False
    dataSetIdFlag['myAnalysisCrosstabs'] = False
    dataSetIdFlag['myAnalysisComparemeans'] = False
    dataSetIdFlag['myAnalysisCrosstabsMultiple'] = False
    dataSetIdFlag['myAnalysisSortWordcloud'] = False
    if caseCondition is not None: dataSetIdFlag['condition'] = {}
    try:
        for analysisRow in analysis:
            if analysisRow["algorithm"] == "frequency":
                dataSetIdFlag['myAnalysisFrequency'] = True
                if frequencyIndex == 4: frequencyIndex = 0
                dataSetIdFlag['frequency'][frequencyIndex].append(str(analysisRow["index"]))
                frequencyIndex += 1
            if analysisRow["algorithm"] == "means" or analysisRow["algorithm"] == "means2":
                dataSetIdFlag['myAnalysisMeans'] = True
                if meansIndex == 4: meansIndex = 0
                dataSetIdFlag['means'][meansIndex].append(str(analysisRow["index"]))
                meansIndex += 1
            if analysisRow["algorithm"] == "crosstabs":
                dataSetIdFlag['myAnalysisCrosstabs'] = True
                if crosstabsIndex == 4: crosstabsIndex = 0
                dataSetIdFlag['crosstabs'][crosstabsIndex].append(str(analysisRow["index"]))
                crosstabsIndex += 1
            if analysisRow["algorithm"] == "comparemeans" or analysisRow["algorithm"] == "comparemeans2" or \
                    analysisRow["algorithm"] == "percentileRank" or analysisRow["algorithm"] == "percentileRank2" or \
                    analysisRow["algorithm"] == "percentileRank3":
                dataSetIdFlag['myAnalysisComparemeans'] = True
                if comparemeansIndex == 4: comparemeansIndex = 0
                dataSetIdFlag['comparemeans'][comparemeansIndex].append(str(analysisRow["index"]))
                comparemeansIndex += 1
            if analysisRow["algorithm"] == "multiple":
                dataSetIdFlag['myAnalysisMultiple'] = True
                if multipleIndex == 4: multipleIndex = 0
                dataSetIdFlag['multiple'][multipleIndex].append(str(analysisRow["index"]))
                multipleIndex += 1
            if analysisRow["algorithm"] == "crosstabsMultiple":
                dataSetIdFlag['myAnalysisCrosstabsMultiple'] = True
                if crosstabsMultipleIndex == 4: crosstabsMultipleIndex = 0
                dataSetIdFlag['crosstabsMultiple'][crosstabsMultipleIndex].append(str(analysisRow["index"]))
                crosstabsMultipleIndex += 1
            if analysisRow["algorithm"] == "sort1" or analysisRow["algorithm"] == "sort2" or \
                    analysisRow["algorithm"] == "crosstabsSort" or analysisRow["algorithm"] == "wordcloud":
                dataSetIdFlag['myAnalysisSortWordcloud'] = True
            dataSetIdChecked = False
            if 'denominator' in analysisRow.keys():analysisThreadFlag = False
            if dataSetIdFlag:
                if str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                    dataSetIdChecked = True

            if not dataSetIdChecked:
                dataSetIdFlag = mongo_dataSetId_logic(PlatID, mongodb_cfg, ProjID,
                                                      str(analysisRow["dataSourceId"]), dataSetIdFlag)
                if caseCondition is not None:
                    if not isinstance(caseCondition, str) and str(analysisRow["dataSourceId"]) in caseCondition.keys():
                        dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])] = \
                            caseCondition[str(analysisRow["dataSourceId"])]
                    else:
                        dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])] = ''
    except Exception as ex:
        my_log.error(ex)
    finally:
        return dataSetIdFlag, analysisThreadFlag


def myAnalysis(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID, fileZipPath,
               dataSetIdFlag, reportError):
    json_data, json_data_flag, json_data_template,dataSetIdIndex, dataSetFlag = {}, True, {},[], {}

    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "53078":
                testFlag = True
            if not os.path.exists(fileZipPath): break
            phrase, phrase2, OptionID, fullMarks, denominator, noCondition, variableGroup, optionGroup, rangeData, \
            phraseText, equalRange, divide, weight, point, deleteRow, idText, json_data_save, optionPoint, \
            percentileRank, removeWord, addWord, replaceText, conditionRank, lengthFilter = \
                "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", True, None, "", None, None, None, None, ""
            formula = ""
            if "phrase" in analysisRow.keys():  phrase = analysisRow["phrase"]
            if "phrase2" in analysisRow.keys(): phrase2 = analysisRow["phrase2"]
            if "equalRange" in analysisRow.keys(): equalRange = analysisRow["equalRange"]
            if "divide" in analysisRow.keys(): divide = str(analysisRow["divide"])
            if "phraseText" in analysisRow.keys(): phraseText = analysisRow["phraseText"]
            if "OptionID" in analysisRow.keys(): OptionID = analysisRow["OptionID"]
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "range" in analysisRow.keys(): rangeData = analysisRow["range"]
            if "weight" in analysisRow.keys(): weight = analysisRow["weight"]
            if "point" in analysisRow.keys(): point = analysisRow["point"]
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if "idText" in analysisRow.keys(): idText = analysisRow["idText"]
            if "removeWord" in analysisRow.keys(): removeWord = analysisRow["removeWord"]
            if "addWord" in analysisRow.keys(): addWord = analysisRow["addWord"]
            if "replaceText" in analysisRow.keys(): replaceText = analysisRow["replaceText"]
            if "formula" in analysisRow.keys(): formula = analysisRow["formula"]
            if "optionPoint" in analysisRow.keys(): optionPoint = analysisRow["optionPoint"]
            if rowDelete: deleteRow = ""
            if "fullMarks" in analysisRow.keys():
                fullMarks,fullMarksNum = str(analysisRow["fullMarks"]).strip(), 0.0
                if fullMarks.find(':') >= 0 and analysisRow["algorithm"] != "percentileRank2":
                    dataFrom = str(fullMarks).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    if datasource["head"][0]["analysis"] == "comparemeans" and str(dataFrom[1]).strip().find("sum") > -1:
                        if str(dataFrom[1]).strip() == "sum":
                            fullMarks = datasource["detailValid"]
                            if "fullMarksDividend" in analysisRow.keys():
                                sumData = str(analysisRow["fullMarksDividend"]).strip().split(':')
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    if str(sumData[0]).strip() == str(detailValidItem["textRow"]).strip():
                                        fullMarks[detailValidIndex][str(dataFrom[1]).strip()] = \
                                            detailValidItem[str(dataFrom[1]).strip()] / float(sumData[1])
                        else:
                            fullMarks = datasource["detailValid"]
                            sumData = str(dataFrom[1]).strip().split('/')
                            if is_number(sumData[1]):
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    fullMarks[detailValidIndex][sumData[0]] = \
                                        detailValidItem[sumData[0]] / float(sumData[1])
                            else:
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    fullMarks[detailValidIndex][sumData[0]] = \
                                        detailValidItem[sumData[0]] / float(detailValidItem[sumData[1]])
                    else:
                        for detailValidItem in datasource["detailValid"]:
                            fullMarksNum += float(str(detailValidItem[dataFrom[1]]))
                        fullMarks = str(fullMarksNum)
            if "variableGroup" in analysisRow.keys():
                variableGroup = analysisRow["variableGroup"]
                if isinstance(variableGroup, str) and variableGroup.find(':') >= 0:
                    dataFrom = str(variableGroup).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    variableGroup = []
                    for detailValidItem in datasource["detailValid"]:
                        variableGroup.append(detailValidItem[dataFrom[1]])
            if "optionGroup" in analysisRow.keys():
                optionGroup = analysisRow["optionGroup"]
                if isinstance(optionGroup, str) and optionGroup.find(':') >= 0:
                    dataFrom = str(optionGroup).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    optionGroup = []
                    for detailValidItem in datasource["detailValid"]:
                        optionGroup.append(detailValidItem[dataFrom[1]])
            if "denominator" in analysisRow.keys():
                dataFrom = str(analysisRow["denominator"]).strip().split(':')
                datasource = json.loads(json_data[dataFrom[0]])
                head = datasource["head"][0]
                if head["analysis"] == "means":
                    denominator = str(head[dataFrom[1]]).strip()
                else:
                    detailValid = datasource["detailValid"]
                    denominator = []
                    denominatorText = []
                    denominatorData = []
                    for dataItem in detailValid:
                        denominatorText.append(dataItem["textRow"])
                        denominatorData.append(dataItem[dataFrom[1]])
                    denominator.append(denominatorText)
                    denominator.append(denominatorData)
            if not isinstance(deleteRow, dict) and str(deleteRow).strip() != "":
                if is_number(deleteRow):
                    if analysisRow["algorithm"] == "crosstabs" or analysisRow["algorithm"] == "crosstabsMultiple" or \
                            analysisRow["algorithm"] == "crosstabsSort":
                        deleteRow = {"total": int(deleteRow)}
                    else:
                        deleteRow = {"count": int(deleteRow)}
                elif str(deleteRow).find('length') > -1 and check_json_format(deleteRow):
                    deleteRowDict = json.loads(deleteRow)
                    if str(deleteRowDict["length"]).find('data') > -1 and str(deleteRowDict["length"]).find(':') > -1:
                        lengthFilter = deleteRowDict
                        deleteRow = ''
                else:
                    if str(deleteRow).strip().find('data') > -1 and str(deleteRow).strip().find(':') > -1:
                        percentileRank = str(deleteRow).strip().split(':')
                    if str(deleteRow).strip().find('percentileRank') > -1:
                        if not isinstance(deleteRow, dict):
                            conditionRank = json.loads(deleteRow)
                        else:
                            conditionRank = deleteRow
                    deleteRow = ''
            if isinstance(deleteRow, dict) and str(deleteRow).strip().find('percentileRank') > -1:
                conditionRank = deleteRow
                deleteRow = ''
            if noCondition != "" and TempID != "":
                if not json_data_template:
                    json_data_mongo = mongo_analysis_template_select(PlatID, mongodb_cfg, ProjID, TempID)
                    for json_data_mongo_item in json_data_mongo:
                        json_data_template = json_data_mongo_item
                        break
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                json_data['data' + str(analysisRow["index"])] = \
                    json_data_template['json_data']['data' + str(analysisRow["index"])]
            else:
                if conditionRank is not None:
                    noConditionRank = ''
                    if 'noCondition' in conditionRank['percentileRank'].keys():
                        noConditionRank = conditionRank['percentileRank']['noCondition']
                    conditionRank['percentileRank']['condition'] = \
                        caseCondition(PlatID, mongodb_cfg, ProjID, Condition, analysisRow, noConditionRank,
                                      json_data, replaceCondition)
                if analysisRow["algorithm"] == "frequency":
                    datasource = mongo_frequency_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                       analysisRow["variable"], phrase, weight, point, idText,
                                                       deleteRow, dataSetIdFlag,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, Condition,
                                                                     analysisRow,
                                                                     noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "means":
                    if "variable" in analysisRow.keys():
                        datasource = mongo_means_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                       analysisRow["variable"], variableGroup, optionGroup, rangeData,
                                                       phrase, fullMarks, denominator, weight, formula, dataSetIdFlag,
                                                       noCondition, replaceText,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, Condition,
                                                                     analysisRow,
                                                                     noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_means_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                       "",
                                                       variableGroup, optionGroup, rangeData, phrase, fullMarks,
                                                       denominator, weight, formula, dataSetIdFlag, noCondition,
                                                       replaceText,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, Condition,
                                                                     analysisRow,
                                                                     noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "means2":
                    if isinstance(variableGroup, str) and str(variableGroup) == "":
                        variableGroup = [analysisRow["variable"]]
                    datasource = mongo_means2_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                    variableGroup, optionGroup, phrase, fullMarks, denominator,
                                                    weight, formula, dataSetIdFlag,
                                                    caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow,
                                                                  noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "multiple":
                    if (isinstance(OptionID, str) and OptionID == "") and str(analysisRow["variable"]).find(',') < 0:
                        datasource = mongo_multiple_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                          analysisRow["variable"], phrase, weight, dataSetIdFlag,
                                                          caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow,
                                                                        noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_multiple2_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                          analysisRow["variable"], phrase, OptionID, weight, dataSetIdFlag,
                                                          caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow,
                                                                         noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "crosstabsMultiple":
                    if (isinstance(OptionID, str) and OptionID == "") and str(analysisRow["ColumnID"]).find(',') < 0:
                        datasource = mongo_crosstabsMultiple_logic(PlatID, mongodb_cfg, ProjID,
                                                                   str(analysisRow["dataSourceId"]),
                                                                   analysisRow["RowID"], analysisRow["ColumnID"],
                                                                   phrase, deleteRow, idText, weight, dataSetIdFlag,
                                                                   caseCondition(PlatID, ProjID, mongodb_cfg, Condition,
                                                                                 analysisRow,
                                                                                 noCondition, json_data,
                                                                                 replaceCondition))
                    else:
                        datasource = mongo_crosstabsMultiple2_logic(PlatID, mongodb_cfg, ProjID,
                                                                    str(analysisRow["dataSourceId"]),
                                                                    analysisRow["RowID"], analysisRow["ColumnID"],
                                                                    phrase, OptionID, deleteRow, idText, weight,
                                                                    dataSetIdFlag,
                                                                    caseCondition(PlatID, ProjID, mongodb_cfg,
                                                                                  Condition, analysisRow,
                                                                                  noCondition, json_data,
                                                                                  replaceCondition))
                elif analysisRow["algorithm"] == "wordcloud":
                    datasource = mongo_wordcloud_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                       analysisRow["variable"], phrase, dataSetIdFlag, removeWord, addWord,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow,
                                                                     noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "crosstabs":
                    if "group" in analysisRow.keys():
                        datasource = mongo_crosstabs_logic(PlatID, mongodb_cfg, ProjID,
                                                           str(analysisRow["dataSourceId"]), analysisRow["RowID"],
                                                           analysisRow["ColumnID"], analysisRow["group"], deleteRow,
                                                           idText, weight, dataSetIdFlag,
                                                           caseCondition(PlatID, mongodb_cfg, ProjID, Condition, analysisRow,
                                                                         noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_crosstabs_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                           analysisRow["RowID"], analysisRow["ColumnID"],
                                                           None, deleteRow, idText, weight, dataSetIdFlag,
                                                           caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow,
                                                                         noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "comparemeans":
                    if "ColumnID" in analysisRow.keys():
                        datasource = mongo_comparemeans_logic(PlatID, mongodb_cfg, ProjID,
                                                              str(analysisRow["dataSourceId"]),
                                                              analysisRow["RowID"],
                                                              analysisRow["ColumnID"], variableGroup, optionGroup,
                                                              rangeData, denominator, deleteRow, idText, weight,
                                                              formula, dataSetIdFlag, conditionRank, replaceText,
                                                              caseCondition(PlatID, mongodb_cfg, ProjID, Condition,
                                                                            analysisRow, noCondition, json_data,
                                                                            replaceCondition))
                    else:
                        datasource = mongo_comparemeans_logic(PlatID, mongodb_cfg, ProjID,
                                                              str(analysisRow["dataSourceId"]),
                                                              analysisRow["RowID"], "", variableGroup, optionGroup,
                                                              rangeData, denominator, deleteRow, idText, weight,
                                                              formula, dataSetIdFlag, conditionRank, replaceText,
                                                              caseCondition(PlatID, ProjID, mongodb_cfg, Condition,
                                                                            analysisRow, noCondition, json_data,
                                                                            replaceCondition))
                elif analysisRow["algorithm"] == "comparemeans2":
                    if isinstance(variableGroup, str) and str(variableGroup) == "":
                        variableGroup = [analysisRow["ColumnID"]]
                    datasource = mongo_comparemeans2_logic(PlatID, mongodb_cfg, ProjID,
                                                           str(analysisRow["dataSourceId"]),
                                                           analysisRow["RowID"], variableGroup, optionGroup,
                                                           denominator, deleteRow, idText, weight, formula,
                                                           dataSetIdFlag, conditionRank,
                                                           caseCondition(PlatID, ProjID, mongodb_cfg, Condition,
                                                                         analysisRow, noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "sort1":
                    datasource = mongo_sort_logic(PlatID, mongodb_cfg, ProjID,
                                                  str(analysisRow["dataSourceId"]),
                                                  analysisRow["VariableID1"],
                                                  analysisRow["VariableID2"],
                                                  analysisRow["VariableID3"],point, dataSetIdFlag,
                                                  caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow,
                                                                noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "sort2":
                    if isinstance(phrase, list) and isinstance(OptionID, list):
                        phraseNew = {}
                        for optionIndex, optionItem in enumerate(OptionID):
                            if optionIndex < len(phrase):
                                phraseNew[optionItem] = phrase[optionIndex]
                        phrase = phraseNew
                    datasource = mongo_sort2_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                   analysisRow["variable"], phrase, point, optionPoint, dataSetIdFlag,
                                                   caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow,
                                                                 noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "crosstabsSort":
                    if isinstance(phrase, list) and isinstance(OptionID, list):
                        phraseNew = {}
                        for optionIndex, optionItem in enumerate(OptionID):
                            if optionIndex < len(phrase):
                                phraseNew[optionItem] = phrase[optionIndex]
                        phrase = phraseNew
                    datasource = mongo_crosstabsSort2_logic(PlatID, mongodb_cfg, ProjID,
                                                            str(analysisRow["dataSourceId"]),
                                                            analysisRow["RowID"], analysisRow["ColumnID"], phrase,
                                                            point, optionPoint, dataSetIdFlag, deleteRow, idText,
                                                            caseCondition(PlatID, ProjID, mongodb_cfg, Condition,
                                                                          analysisRow,
                                                                          noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "percentileRank" or analysisRow["algorithm"] == "percentileRank2"  or \
                        analysisRow["algorithm"] == "percentileRank3":
                    if "filter1" in analysisRow.keys():
                        Condition1 = analysisRow["filter1"]
                        if check_json_format(json.dumps(Condition1)):
                            keys,values = [],[]
                            for key, value in Condition1.items():
                                keys.append(key)
                                if check_json_format(json.dumps(value)):
                                    valueNew = {}
                                    for keyWords, valueWords in value.items():
                                        if str(keyWords).strip() == "lte" or str(keyWords).strip() == "gte" or \
                                                str(keyWords).strip() == "gt" or str(keyWords).strip() == "lt" or \
                                                str(keyWords).strip() == "nin" or str(keyWords).strip() == "in" or \
                                                str(keyWords).strip() == "regex" or str(keyWords).strip() == "ne" :
                                            if isinstance(valueWords, str) and str(valueWords).find(':') > -1:
                                                dataFrom = str(valueWords).strip().split(':')
                                                datasource = json.loads(json_data[dataFrom[0]])
                                                valueWords = datasource["head"][0][dataFrom[1]]
                                            if isinstance(equalRange, str) and str(equalRange) != "":
                                                equalRangeData = str(equalRange).strip().split(':')
                                                if is_number(valueWords) and valueWords - math.floor(valueWords) == 0\
                                                        and keyWords == equalRangeData[0]:
                                                    keyWords = equalRangeData[1]
                                            keyWords = "$" + str(keyWords).strip()
                                        if replaceCondition is not None:
                                            for replaceIndex, replaceItem in enumerate(replaceCondition[0]):
                                                if {key: value} == replaceCondition[1][replaceIndex]:
                                                    for keyReplace, valueReplace in replaceItem.items():
                                                        if key == keyReplace:
                                                            valueWords = valueReplace
                                        valueNew[keyWords] = valueWords
                                    values.append(valueNew)
                                else:
                                    if isinstance(value, str) and str(value).find(':') > -1:
                                        dataFrom = str(value).strip().split(':')
                                        datasource = json.loads(json_data[dataFrom[0]])
                                        value = datasource["head"][0][dataFrom[1]]
                                    if replaceCondition is not None:
                                        for replaceIndex, replaceItem in enumerate(replaceCondition[0]):
                                            if {key: value} == replaceCondition[1][replaceIndex]:
                                                for keyReplace, valueReplace in replaceItem.items():
                                                    if key == keyReplace:
                                                        value = valueReplace
                                    values.append(value)
                            Condition1 = [keys, values]
                    else:
                        Condition1 = None
                    Condition2 = caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow, "", json_data,
                                               replaceCondition)
                    Condition3 = caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow, "false", json_data,
                                               replaceCondition)
                    if analysisRow["algorithm"] == "percentileRank":
                        datasource = mongo_percentileRank_logic(PlatID, mongodb_cfg, ProjID,
                                                                str(analysisRow["dataSourceId1"]),
                                                                str(analysisRow["dataSourceId2"]),
                                                                str(analysisRow["RowID"]),
                                                                str(analysisRow["variable1"]),
                                                                analysisRow["variable2"],variableGroup, phrase, phraseText,
                                                                fullMarks, divide, dataSetIdFlag,
                                                                Condition1, Condition2, Condition3)
                    elif analysisRow["algorithm"] == "percentileRank2":
                        datasource = mongo_percentileRank2_logic(PlatID, mongodb_cfg, ProjID,
                                                                 str(analysisRow["dataSourceId1"]),
                                                                 str(analysisRow["dataSourceId2"]),
                                                                 str(analysisRow["RowID"]),
                                                                 str(analysisRow["variable1"]),
                                                                 analysisRow["variable2"], variableGroup, phrase, phrase2,
                                                                 phraseText, fullMarks, divide, dataSetIdFlag,
                                                                 Condition1, Condition2, Condition3)
                    elif analysisRow["algorithm"] == "percentileRank3":
                        datasource = mongo_percentileRank3_logic(PlatID, mongodb_cfg, ProjID,
                                                                 str(analysisRow["dataSourceId1"]),
                                                                 str(analysisRow["dataSourceId2"]),
                                                                 str(analysisRow["RowID"]),
                                                                 str(analysisRow["variable1"]),
                                                                 analysisRow["variable2"], variableGroup, phrase, phrase2,
                                                                 phraseText, fullMarks, divide, dataSetIdFlag,
                                                                 Condition1, Condition2, Condition3)
                    else:
                        datasource = mongo_percentileRank4_logic(PlatID, mongodb_cfg, ProjID,
                                                                 str(analysisRow["dataSourceId1"]),
                                                                str(analysisRow["dataSourceId2"]),
                                                                str(analysisRow["RowID"]),
                                                                str(analysisRow["variable1"]),
                                                                analysisRow["variable2"], variableGroup, phrase, phraseText,
                                                                fullMarks, divide, dataSetIdFlag,
                                                                 Condition1, Condition2, Condition3)
                else:
                    datasource = None
                if datasource is not None and datasource:
                    if not isinstance(percentileRank, str):
                        datasource['head'][0]['percentileRank'] = percentileRank
                    if not isinstance(lengthFilter, str):
                        datasource['head'][0]['lengthFilter'] = lengthFilter
                    datasource['head'][0]['noCondition'] = noCondition
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            print(ex)
            my_log.error(ex)
            json_data_flag = False
    return json_data, json_data_flag


def myAnalysisThread(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID, fileZipPath,
                     dataSetIdFlag, reportError):
    json_data, json_data_flag, threadCondition, json_data_template = \
        {}, True, copy.deepcopy(Condition), {}
    if TempID != "":
        if not json_data_template:
            json_data_mongo = mongo_analysis_template_select(PlatID, mongodb_cfg, ProjID, TempID)
            for json_data_mongo_item in json_data_mongo:
                json_data_template = json_data_mongo_item
                break
    try:
        # 定义系统资源检查函数
        def check_system_resources():
            try:
                # 获取 CPU 使用率
                cpu_usage = psutil.cpu_percent(interval=0.01)  # 进一步缩短检查间隔，提高响应速度
                # 获取内存使用率
                memory_usage = psutil.virtual_memory().percent
                # 检查是否有足够的资源（提高阈值，允许更高的资源利用率）
                return cpu_usage < 90 and memory_usage < 90
            except Exception:
                # 如果无法获取系统资源信息，默认返回 True
                return True

        # 获取系统信息
        cpu_count = multiprocessing.cpu_count()
        # 根据系统资源动态调整线程池大小（最大化线程池大小）
        max_workers = min(cpu_count * 6, 32)  # 大幅增加线程池大小，最多32个线程

        # 创建线程池
        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
            # 所有任务配置
            task_configs = []
            base_functions = [myAnalysisFrequency, myAnalysisMeans, myAnalysisMultiple, myAnalysisCrosstabs,
                              myAnalysisComparemeans, myAnalysisCrosstabsMultiple]

            # 构建任务列表
            for func in base_functions:
                if dataSetIdFlag.get(func.__name__, False):
                    for threadIndex in range(4):
                        args = (PlatID, ProjID, mongodb_cfg, analysis, threadCondition,
                                replaceCondition, rowDelete, TempID, json_data, json_data_template,
                                fileZipPath, dataSetIdFlag, threadIndex, reportError)
                        task_configs.append((func, args, f"{func.__name__}[{threadIndex}]"))

            if dataSetIdFlag.get("myAnalysisSortWordcloud", False):
                # 排序和词云分析任务
                args = (PlatID, ProjID, mongodb_cfg, analysis, threadCondition,
                        replaceCondition, rowDelete, TempID, json_data, json_data_template,
                        fileZipPath, dataSetIdFlag, reportError)
                task_configs.append((myAnalysisSortWordcloud, args, "myAnalysisSortWordcloud"))

            # 动态提交任务，根据资源使用情况实时调整
            pending_tasks = task_configs.copy()
            active_futures = []

            # 持续提交任务，直到所有任务都已提交
            while pending_tasks:
                # 检查系统资源
                if check_system_resources():
                    # 有空闲资源，提交任务
                    task = pending_tasks.pop(0)
                    func, args, task_name = task
                    future = executor.submit(func, *args)
                    active_futures.append((future, task_name))
                else:
                    # 资源不足，短暂等待
                    time.sleep(0.05)  # 进一步缩短等待时间

                # 清理已完成的任务，释放资源
                completed_futures = []
                for i, (future, task_name) in enumerate(active_futures):
                    if future.done():
                        try:
                            future.result()
                            completed_futures.append(i)
                        except Exception as ex:
                            reportError[f"error_{task_name}"] = f"❌ 任务失败: {task_name} - {ex}"
                            json_data_flag = False

                # 从列表中移除已完成的任务
                for i in reversed(completed_futures):
                    del active_futures[i]

            # 等待所有任务完成
            for future, task_name in active_futures:
                try:
                    future.result()
                except Exception as ex:
                    reportError[f"error_{task_name}"] = f"❌ 任务失败: {task_name} - {ex}"
                    json_data_flag = False

        # 检查最终结果
        if 'json_data_flag' in json_data:
            json_data_flag = False
    except Exception as ex:
        reportError["errorAnalysis"] = str(ex)
        json_data_flag = False
    finally:
        # 强制垃圾回收
        gc.collect()
        return dict(json_data), json_data_flag


def myAnalysisFrequency(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID,
                        json_data, json_data_template, fileZipPath, dataSetIdFlag, flagIndex, reportError):
    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "201":
                testFlag = True
            if not os.path.exists(fileZipPath):break
            if str(analysisRow["index"]) not in dataSetIdFlag['frequency'][flagIndex]:
                continue
            phrase, noCondition, lengthFilter, weight, point, deleteRow, idText, json_data_save =  \
                "", "", "", "", "", "", "", True
            if "phrase" in analysisRow.keys():  phrase = analysisRow["phrase"]
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "weight" in analysisRow.keys(): weight = analysisRow["weight"]
            if "point" in analysisRow.keys(): point = analysisRow["point"]
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if "idText" in analysisRow.keys(): idText = analysisRow["idText"]
            if rowDelete: deleteRow = ""
            if not isinstance(deleteRow, dict) and str(deleteRow).strip() != "":
                if is_number(deleteRow):
                    if analysisRow["algorithm"] == "crosstabs" or analysisRow["algorithm"] == "crosstabsMultiple"  or \
                            analysisRow["algorithm"] == "crosstabsSort":
                        deleteRow = {"total": int(deleteRow)}
                    else:
                        deleteRow = {"count": int(deleteRow)}
                elif str(deleteRow).find('length') > -1 and check_json_format(deleteRow):
                    deleteRowDict = json.loads(deleteRow)
                    if str(deleteRowDict["length"]).find('data') > -1 and str(deleteRowDict["length"]).find(':') > -1:
                        lengthFilter = deleteRowDict
                        deleteRow = ''
                else:
                    deleteRow = ''
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                pass
            else:
                if analysisRow["algorithm"] == "frequency":
                    if dataSetIdFlag and 'condition' in dataSetIdFlag.keys() and 'dataSetId' in dataSetIdFlag.keys() and\
                        str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                        copyCondition = copy.deepcopy(dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])])
                    else:
                        copyCondition = copy.deepcopy(Condition)
                    datasource = mongo_frequency_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                       analysisRow["variable"], phrase, weight, point, idText,
                                                       deleteRow, dataSetIdFlag,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                     noCondition,json_data, replaceCondition))
                else:
                    datasource = None
                if datasource is not None and datasource:
                    if not isinstance(lengthFilter, str):
                        datasource['head'][0]['lengthFilter'] = lengthFilter
                    datasource['head'][0]['noCondition'] = noCondition
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            json_data['json_data_flag'] = False


def myAnalysisMeans(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID,
                    json_data, json_data_template, fileZipPath, dataSetIdFlag, flagIndex, reportError):
    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "192":
                testFlag = True
            if not os.path.exists(fileZipPath):break
            if str(analysisRow["index"]) not in dataSetIdFlag['means'][flagIndex]:
                continue
            phrase, fullMarks, denominator, noCondition, variableGroup, optionGroup, rangeData, \
            weight, deleteRow, json_data_save, replaceText, formula =  "", "", "", "", "", "", "", "", "", True, None,""
            if "phrase" in analysisRow.keys():  phrase = analysisRow["phrase"]
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "range" in analysisRow.keys(): rangeData = analysisRow["range"]
            if "weight" in analysisRow.keys(): weight = analysisRow["weight"]
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if rowDelete: deleteRow = ""
            if "replaceText" in analysisRow.keys(): replaceText = analysisRow["replaceText"]
            if "formula" in analysisRow.keys(): formula = analysisRow["formula"]
            if "fullMarks" in analysisRow.keys():
                fullMarks,fullMarksNum = str(analysisRow["fullMarks"]).strip(), 0.0
                if fullMarks.find(':') >= 0 and analysisRow["algorithm"] != "percentileRank2":
                    dataFrom = str(fullMarks).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    if datasource["head"][0]["analysis"] == "comparemeans" and str(dataFrom[1]).strip().find("sum") > -1:
                        if str(dataFrom[1]).strip() == "sum":
                            fullMarks = datasource["detailValid"]
                            if "fullMarksDividend" in analysisRow.keys():
                                sumData = str(analysisRow["fullMarksDividend"]).strip().split(':')
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    if str(sumData[0]).strip() == str(detailValidItem["textRow"]).strip():
                                        fullMarks[detailValidIndex][str(dataFrom[1]).strip()] = \
                                            detailValidItem[str(dataFrom[1]).strip()] / float(sumData[1])
                        else:
                            fullMarks = datasource["detailValid"]
                            sumData = str(dataFrom[1]).strip().split('/')
                            if is_number(sumData[1]):
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    fullMarks[detailValidIndex][sumData[0]] = \
                                        detailValidItem[sumData[0]] / float(sumData[1])
                            else:
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    fullMarks[detailValidIndex][sumData[0]] = \
                                        detailValidItem[sumData[0]] / float(detailValidItem[sumData[1]])
                    else:
                        for detailValidItem in datasource["detailValid"]:
                            fullMarksNum += float(str(detailValidItem[dataFrom[1]]))
                        fullMarks = str(fullMarksNum)
            if "variableGroup" in analysisRow.keys():
                variableGroup = analysisRow["variableGroup"]
                if isinstance(variableGroup, str) and variableGroup.find(':') >= 0:
                    dataFrom = str(variableGroup).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    variableGroup = []
                    for detailValidItem in datasource["detailValid"]:
                        variableGroup.append(detailValidItem[dataFrom[1]])
            if "optionGroup" in analysisRow.keys():
                optionGroup = analysisRow["optionGroup"]
                if isinstance(optionGroup, str) and optionGroup.find(':') >= 0:
                    dataFrom = str(optionGroup).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    optionGroup = []
                    for detailValidItem in datasource["detailValid"]:
                        optionGroup.append(detailValidItem[dataFrom[1]])
            if "denominator" in analysisRow.keys():
                dataFrom = str(analysisRow["denominator"]).strip().split(':')
                datasource = json.loads(json_data[dataFrom[0]])
                head = datasource["head"][0]
                if head["analysis"] == "means":
                    denominator = str(head[dataFrom[1]]).strip()
                else:
                    detailValid = datasource["detailValid"]
                    denominator = []
                    denominatorText = []
                    denominatorData = []
                    for dataItem in detailValid:
                        denominatorText.append(dataItem["textRow"])
                        denominatorData.append(dataItem[dataFrom[1]])
                    denominator.append(denominatorText)
                    denominator.append(denominatorData)
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                pass
            else:
                if dataSetIdFlag and 'condition' in dataSetIdFlag.keys() and 'dataSetId' in dataSetIdFlag.keys() and \
                        str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                    copyCondition = copy.deepcopy(dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])])
                else:
                    copyCondition = copy.deepcopy(Condition)
                if analysisRow["algorithm"] == "means":
                    if "variable" in analysisRow.keys():
                        datasource = mongo_means_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                       analysisRow["variable"], variableGroup, optionGroup, rangeData,
                                                       phrase, fullMarks, denominator, weight, formula, dataSetIdFlag,
                                                       noCondition, replaceText,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                     noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_means_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]), "",
                                                       variableGroup, optionGroup, rangeData, phrase, fullMarks,
                                                       denominator, weight, formula, dataSetIdFlag, noCondition, replaceText,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                     noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "means2":
                    if isinstance(variableGroup, str) and str(variableGroup) == "":
                        variableGroup = [analysisRow["variable"]]
                    datasource = mongo_means2_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                    variableGroup, optionGroup, phrase, fullMarks, denominator,
                                                    weight, formula, dataSetIdFlag,
                                                    caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                  noCondition, json_data, replaceCondition))
                else:
                    datasource = None
                if datasource is not None and datasource:
                    datasource['head'][0]['noCondition'] = noCondition
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            json_data['json_data_flag'] = False


def myAnalysisMultiple(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID,
                       json_data, json_data_template, fileZipPath, dataSetIdFlag, flagIndex, reportError):
    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "174":
                testFlag = True
            if not os.path.exists(fileZipPath):break
            if str(analysisRow["index"]) not in dataSetIdFlag['multiple'][flagIndex]:
                continue
            phrase, OptionID, noCondition, weight, deleteRow, json_data_save, idText =  \
                "", "", "", "", "", True, ""
            if "phrase" in analysisRow.keys():  phrase = analysisRow["phrase"]
            if "OptionID" in analysisRow.keys(): OptionID = analysisRow["OptionID"]
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "weight" in analysisRow.keys(): weight = analysisRow["weight"]
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if "idText" in analysisRow.keys(): idText = analysisRow["idText"]
            if rowDelete: deleteRow = ""
            if not isinstance(deleteRow, dict) and str(deleteRow).strip() != "":
                if is_number(deleteRow):
                    if analysisRow["algorithm"] == "crosstabs" or analysisRow["algorithm"] == "crosstabsMultiple" or \
                            analysisRow["algorithm"] == "crosstabsSort":
                        deleteRow = {"total": int(deleteRow)}
                    else:
                        deleteRow = {"count": int(deleteRow)}
                else:
                    deleteRow = ''
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                pass
            else:
                if dataSetIdFlag and 'condition' in dataSetIdFlag.keys() and 'dataSetId' in dataSetIdFlag.keys() and \
                        str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                    copyCondition = copy.deepcopy(dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])])
                else:
                    copyCondition = copy.deepcopy(Condition)
                if analysisRow["algorithm"] == "multiple":
                    if (isinstance(OptionID, str) and OptionID == "") and str(analysisRow["variable"]).find(',') < 0:
                        datasource = mongo_multiple_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                          analysisRow["variable"], phrase, weight, dataSetIdFlag,
                                                          caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition,
                                                                        analysisRow,
                                                                        noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_multiple2_logic(PlatID, mongodb_cfg, ProjID,
                                                           str(analysisRow["dataSourceId"]),
                                                           analysisRow["variable"], phrase, OptionID, weight, dataSetIdFlag,
                                                           caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition,
                                                                         analysisRow,
                                                                         noCondition, json_data, replaceCondition))
                else:
                    datasource = None
                if datasource is not None and datasource:
                    datasource['head'][0]['noCondition'] = noCondition
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            json_data['json_data_flag'] = False


def myAnalysisCrosstabsMultiple(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID,
                                json_data, json_data_template, fileZipPath, dataSetIdFlag, flagIndex, reportError):
    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "174":
                testFlag = True
            if not os.path.exists(fileZipPath):break
            if str(analysisRow["index"]) not in dataSetIdFlag['crosstabsMultiple'][flagIndex]:
                continue
            phrase, OptionID, noCondition, weight, deleteRow, json_data_save, idText =  \
                "", "", "", "", "", True, ""
            if "phrase" in analysisRow.keys():  phrase = analysisRow["phrase"]
            if "OptionID" in analysisRow.keys(): OptionID = analysisRow["OptionID"]
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "weight" in analysisRow.keys(): weight = analysisRow["weight"]
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if "idText" in analysisRow.keys(): idText = analysisRow["idText"]
            if rowDelete: deleteRow = ""
            if not isinstance(deleteRow, dict) and str(deleteRow).strip() != "":
                if is_number(deleteRow):
                    if analysisRow["algorithm"] == "crosstabs" or analysisRow["algorithm"] == "crosstabsMultiple" or \
                            analysisRow["algorithm"] == "crosstabsSort":
                        deleteRow = {"total": int(deleteRow)}
                    else:
                        deleteRow = {"count": int(deleteRow)}
                else:
                    deleteRow = ''
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                pass
            else:
                if dataSetIdFlag and 'condition' in dataSetIdFlag.keys() and 'dataSetId' in dataSetIdFlag.keys() and \
                        str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                    copyCondition = copy.deepcopy(dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])])
                else:
                    copyCondition = copy.deepcopy(Condition)
                if analysisRow["algorithm"] == "crosstabsMultiple":
                    if (isinstance(OptionID, str) and OptionID == "") and str(analysisRow["ColumnID"]).find(',') < 0:
                        datasource = mongo_crosstabsMultiple_logic(PlatID, mongodb_cfg, ProjID,
                                                                   str(analysisRow["dataSourceId"]),
                                                                   analysisRow["RowID"], analysisRow["ColumnID"],
                                                                   phrase, deleteRow, idText, weight, dataSetIdFlag,
                                                          caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition,
                                                                        analysisRow,
                                                                        noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_crosstabsMultiple2_logic(PlatID, mongodb_cfg, ProjID,
                                                                    str(analysisRow["dataSourceId"]),
                                                                    analysisRow["RowID"], analysisRow["ColumnID"],
                                                                    phrase, OptionID, deleteRow, idText, weight, dataSetIdFlag,
                                                          caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition,
                                                                        analysisRow,
                                                                        noCondition, json_data, replaceCondition))
                else:
                    datasource = None
                if datasource is not None and datasource:
                    datasource['head'][0]['noCondition'] = noCondition
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            json_data['json_data_flag'] = False


def myAnalysisCrosstabs(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID,
                        json_data, json_data_template, fileZipPath, dataSetIdFlag, flagIndex, reportError):
    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "480":
                testFlag = True
            if not os.path.exists(fileZipPath):break
            if str(analysisRow["index"]) not in dataSetIdFlag['crosstabs'][flagIndex]:
                continue
            noCondition, weight, point, deleteRow, idText, json_data_save =  "", "", "", "", "", True
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "weight" in analysisRow.keys(): weight = analysisRow["weight"]
            if "point" in analysisRow.keys(): point = analysisRow["point"]
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if "idText" in analysisRow.keys(): idText = analysisRow["idText"]
            if rowDelete: deleteRow = ""
            if not isinstance(deleteRow, dict) and str(deleteRow).strip() != "":
                if is_number(deleteRow):
                    if analysisRow["algorithm"] == "crosstabs":
                        deleteRow = {"total": int(deleteRow)}
                    else:
                        deleteRow = {"count": int(deleteRow)}
                else:
                    deleteRow = ''
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                pass
            else:
                if dataSetIdFlag and 'condition' in dataSetIdFlag.keys() and 'dataSetId' in dataSetIdFlag.keys() and \
                        str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                    copyCondition = copy.deepcopy(dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])])
                else:
                    copyCondition = copy.deepcopy(Condition)
                if analysisRow["algorithm"] == "crosstabs":
                    if "group" in analysisRow.keys():
                        datasource = mongo_crosstabs_logic(PlatID, mongodb_cfg, ProjID,
                                                           str(analysisRow["dataSourceId"]), analysisRow["RowID"],
                                                           analysisRow["ColumnID"], analysisRow["group"], deleteRow,
                                                           idText, weight, dataSetIdFlag,
                                                           caseCondition(PlatID, mongodb_cfg, ProjID, copyCondition, analysisRow,
                                                                         noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_crosstabs_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                           analysisRow["RowID"], analysisRow["ColumnID"],
                                                           None, deleteRow, idText, weight, dataSetIdFlag,
                                                           caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                         noCondition, json_data, replaceCondition))
                else:
                    datasource = None
                if datasource is not None and datasource:
                    datasource['head'][0]['noCondition'] = noCondition
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            json_data['json_data_flag'] = False


def myAnalysisComparemeans(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID,
                           json_data, json_data_template, fileZipPath, dataSetIdFlag, flagIndex, reportError):
    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "480":
                testFlag = True
            if not os.path.exists(fileZipPath):break
            if str(analysisRow["index"]) not in dataSetIdFlag['comparemeans'][flagIndex]:
                continue
            phrase, phrase2, fullMarks, denominator, noCondition, variableGroup, optionGroup, rangeData, \
            phraseText, equalRange, divide, weight, deleteRow, idText, json_data_save, percentileRank, \
            conditionRank, replaceText, formula = \
                "", "", "", "","", "", "", "", "", "","", "", "", "", True, "", None, None, ""
            if "phrase" in analysisRow.keys():  phrase = analysisRow["phrase"]
            if "phrase2" in analysisRow.keys(): phrase2 = analysisRow["phrase2"]
            if "equalRange" in analysisRow.keys(): equalRange = analysisRow["equalRange"]
            if "divide" in analysisRow.keys(): divide = str(analysisRow["divide"])
            if "phraseText" in analysisRow.keys(): phraseText = analysisRow["phraseText"]
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "range" in analysisRow.keys(): rangeData = analysisRow["range"]
            if "weight" in analysisRow.keys(): weight = analysisRow["weight"]
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if "idText" in analysisRow.keys(): idText = analysisRow["idText"]
            if "replaceText" in analysisRow.keys(): replaceText = analysisRow["replaceText"]
            if "formula" in analysisRow.keys(): formula = analysisRow["formula"]
            if rowDelete: deleteRow = ""
            if "fullMarks" in analysisRow.keys():
                fullMarks,fullMarksNum = str(analysisRow["fullMarks"]).strip(), 0.0
                if fullMarks.find(':') >= 0 and analysisRow["algorithm"] != "percentileRank2":
                    dataFrom = str(fullMarks).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    if datasource["head"][0]["analysis"] == "comparemeans" and str(dataFrom[1]).strip().find("sum") > -1:
                        if str(dataFrom[1]).strip() == "sum":
                            fullMarks = datasource["detailValid"]
                            if "fullMarksDividend" in analysisRow.keys():
                                sumData = str(analysisRow["fullMarksDividend"]).strip().split(':')
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    if str(sumData[0]).strip() == str(detailValidItem["textRow"]).strip():
                                        fullMarks[detailValidIndex][str(dataFrom[1]).strip()] = \
                                            detailValidItem[str(dataFrom[1]).strip()] / float(sumData[1])
                        else:
                            fullMarks = datasource["detailValid"]
                            sumData = str(dataFrom[1]).strip().split('/')
                            if is_number(sumData[1]):
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    fullMarks[detailValidIndex][sumData[0]] = \
                                        detailValidItem[sumData[0]] / float(sumData[1])
                            else:
                                for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                    fullMarks[detailValidIndex][sumData[0]] = \
                                        detailValidItem[sumData[0]] / float(detailValidItem[sumData[1]])
                    else:
                        for detailValidItem in datasource["detailValid"]:
                            fullMarksNum += float(str(detailValidItem[dataFrom[1]]))
                        fullMarks = str(fullMarksNum)
            if "variableGroup" in analysisRow.keys():
                variableGroup = analysisRow["variableGroup"]
                if isinstance(variableGroup, str) and variableGroup.find(':') >= 0:
                    dataFrom = str(variableGroup).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    variableGroup = []
                    for detailValidItem in datasource["detailValid"]:
                        variableGroup.append(detailValidItem[dataFrom[1]])
            if "optionGroup" in analysisRow.keys():
                optionGroup = analysisRow["optionGroup"]
                if isinstance(optionGroup, str) and optionGroup.find(':') >= 0:
                    dataFrom = str(optionGroup).strip().split(':')
                    datasource = json.loads(json_data[dataFrom[0]])
                    optionGroup = []
                    for detailValidItem in datasource["detailValid"]:
                        optionGroup.append(detailValidItem[dataFrom[1]])
            if "denominator" in analysisRow.keys():
                dataFrom = str(analysisRow["denominator"]).strip().split(':')
                datasource = json.loads(json_data[dataFrom[0]])
                head = datasource["head"][0]
                if head["analysis"] == "means":
                    denominator = str(head[dataFrom[1]]).strip()
                else:
                    detailValid = datasource["detailValid"]
                    denominator = []
                    denominatorText = []
                    denominatorData = []
                    for dataItem in detailValid:
                        denominatorText.append(dataItem["textRow"])
                        denominatorData.append(dataItem[dataFrom[1]])
                    denominator.append(denominatorText)
                    denominator.append(denominatorData)
            if not isinstance(deleteRow, dict) and str(deleteRow).strip() != "":
                if is_number(deleteRow):
                    if analysisRow["algorithm"] == "crosstabs":
                        deleteRow = {"total": int(deleteRow)}
                    else:
                        deleteRow = {"count": int(deleteRow)}
                else:
                    if str(deleteRow).strip().find('data') > -1 and str(deleteRow).strip().find(':') > -1:
                        percentileRank = str(deleteRow).strip().split(':')
                    if str(deleteRow).strip().find('percentileRank') > -1:
                        if not isinstance(deleteRow, dict):
                            conditionRank = json.loads(deleteRow)
                        else:
                            conditionRank = deleteRow
                    deleteRow = ''
            if isinstance(deleteRow, dict) and str(deleteRow).strip().find('percentileRank') > -1:
                conditionRank = deleteRow
                deleteRow = ''
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                pass
            else:
                if dataSetIdFlag and 'condition' in dataSetIdFlag.keys() and 'dataSetId' in dataSetIdFlag.keys() and \
                        str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                    copyCondition = copy.deepcopy(dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])])
                else:
                    copyCondition = copy.deepcopy(Condition)
                if conditionRank is not None:
                    noConditionRank = ''
                    if 'noCondition' in conditionRank['percentileRank'].keys():
                        noConditionRank = conditionRank['percentileRank']['noCondition']
                    conditionRank['percentileRank']['condition'] = \
                        caseCondition(PlatID, mongodb_cfg, ProjID, copyCondition, analysisRow, noConditionRank,
                                      json_data, replaceCondition)
                if analysisRow["algorithm"] == "comparemeans":
                    if "ColumnID" in analysisRow.keys():
                        datasource = mongo_comparemeans_logic(PlatID, mongodb_cfg, ProjID,
                                                              str(analysisRow["dataSourceId"]), analysisRow["RowID"],
                                                              analysisRow["ColumnID"], variableGroup, optionGroup,
                                                              rangeData, denominator, deleteRow, idText, weight, formula,
                                                              dataSetIdFlag, conditionRank, replaceText,
                                                              caseCondition(PlatID, mongodb_cfg, ProjID, copyCondition, analysisRow,
                                                                            noCondition, json_data, replaceCondition))
                    else:
                        datasource = mongo_comparemeans_logic(PlatID, mongodb_cfg, ProjID,
                                                              str(analysisRow["dataSourceId"]),
                                                              analysisRow["RowID"], "", variableGroup, optionGroup,
                                                              rangeData, denominator, deleteRow, idText, weight, formula,
                                                              dataSetIdFlag, conditionRank, replaceText,
                                                              caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                            noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "comparemeans2":
                    if isinstance(variableGroup, str) and str(variableGroup) == "":
                        variableGroup = [analysisRow["ColumnID"]]
                    datasource = mongo_comparemeans2_logic(PlatID, mongodb_cfg, ProjID,str(analysisRow["dataSourceId"]),
                                                           analysisRow["RowID"], variableGroup, optionGroup,
                                                           denominator, deleteRow, idText, weight, formula,
                                                           dataSetIdFlag, conditionRank,
                                                           caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                         noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "percentileRank" or analysisRow["algorithm"] == "percentileRank2"  or \
                        analysisRow["algorithm"] == "percentileRank3":
                    if "filter1" in analysisRow.keys():
                        Condition1 = analysisRow["filter1"]
                        if check_json_format(json.dumps(Condition1)):
                            keys,values = [],[]
                            for key, value in Condition1.items():
                                keys.append(key)
                                if check_json_format(json.dumps(value)):
                                    valueNew = {}
                                    for keyWords, valueWords in value.items():
                                        if str(keyWords).strip() == "lte" or str(keyWords).strip() == "gte" or \
                                                str(keyWords).strip() == "gt" or str(keyWords).strip() == "lt" or \
                                                str(keyWords).strip() == "nin" or str(keyWords).strip() == "in" or \
                                                str(keyWords).strip() == "regex" or str(keyWords).strip() == "ne" :
                                            if isinstance(valueWords, str) and str(valueWords).find(':') > -1:
                                                dataFrom = str(valueWords).strip().split(':')
                                                datasource = json.loads(json_data[dataFrom[0]])
                                                valueWords = datasource["head"][0][dataFrom[1]]
                                            if isinstance(equalRange, str) and str(equalRange) != "":
                                                equalRangeData = str(equalRange).strip().split(':')
                                                if is_number(valueWords) and valueWords - math.floor(valueWords) == 0\
                                                        and keyWords == equalRangeData[0]:
                                                    keyWords = equalRangeData[1]
                                            keyWords = "$" + str(keyWords).strip()
                                        if replaceCondition is not None:
                                            for replaceIndex, replaceItem in enumerate(replaceCondition[0]):
                                                if {key:value} == replaceCondition[1][replaceIndex]:
                                                    for keyReplace, valueReplace in replaceItem.items():
                                                        if key == keyReplace:
                                                            valueWords = valueReplace
                                        valueNew[keyWords] = valueWords
                                    values.append(valueNew)
                                else:
                                    if isinstance(value, str) and str(value).find(':') > -1:
                                        dataFrom = str(value).strip().split(':')
                                        datasource = json.loads(json_data[dataFrom[0]])
                                        value = datasource["head"][0][dataFrom[1]]
                                    if replaceCondition is not None:
                                        for replaceIndex, replaceItem in enumerate(replaceCondition[0]):
                                            if {key:value} == replaceCondition[1][replaceIndex]:
                                                for keyReplace, valueReplace in replaceItem.items():
                                                    if key == keyReplace:
                                                        value = valueReplace
                                    values.append(value)
                            Condition1 = [keys, values]
                    else:
                        Condition1 = None
                    Condition2 = caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow, "", json_data,
                                               replaceCondition)
                    Condition3 = caseCondition(PlatID, ProjID, mongodb_cfg, Condition, analysisRow, "false", json_data,
                                               replaceCondition)
                    if analysisRow["algorithm"] == "percentileRank":
                        datasource = mongo_percentileRank_logic(PlatID, mongodb_cfg, ProjID,
                                                                str(analysisRow["dataSourceId1"]),
                                                                str(analysisRow["dataSourceId2"]),
                                                                str(analysisRow["RowID"]),
                                                                str(analysisRow["variable1"]),
                                                                analysisRow["variable2"],variableGroup, phrase, phraseText,
                                                                fullMarks, divide, dataSetIdFlag,
                                                                Condition1, Condition2, Condition3)
                    elif analysisRow["algorithm"] == "percentileRank2":
                        datasource = mongo_percentileRank2_logic(PlatID, mongodb_cfg, ProjID,
                                                                 str(analysisRow["dataSourceId1"]),
                                                                 str(analysisRow["dataSourceId2"]),
                                                                 str(analysisRow["RowID"]),
                                                                 str(analysisRow["variable1"]),
                                                                 analysisRow["variable2"], variableGroup, phrase, phrase2,
                                                                 phraseText, fullMarks, divide, dataSetIdFlag,
                                                                 Condition1, Condition2, Condition3)
                    elif analysisRow["algorithm"] == "percentileRank3":
                        datasource = mongo_percentileRank3_logic(PlatID, mongodb_cfg, ProjID,
                                                                 str(analysisRow["dataSourceId1"]),
                                                                 str(analysisRow["dataSourceId2"]),
                                                                 str(analysisRow["RowID"]),
                                                                 str(analysisRow["variable1"]),
                                                                 analysisRow["variable2"], variableGroup, phrase, phrase2,
                                                                 phraseText, fullMarks, divide, dataSetIdFlag,
                                                                 Condition1, Condition2, Condition3)
                    else:
                        datasource = mongo_percentileRank4_logic(PlatID, mongodb_cfg, ProjID,
                                                                 str(analysisRow["dataSourceId1"]),
                                                                str(analysisRow["dataSourceId2"]),
                                                                str(analysisRow["RowID"]),
                                                                str(analysisRow["variable1"]),
                                                                analysisRow["variable2"], variableGroup, phrase, phraseText,
                                                                fullMarks, divide, dataSetIdFlag,
                                                                 Condition1, Condition2, Condition3)
                else:
                    datasource = None
                if datasource is not None and datasource:
                    datasource['head'][0]['noCondition'] = noCondition
                    if not isinstance(percentileRank, str):
                        datasource['head'][0]['percentileRank'] = percentileRank
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            json_data['json_data_flag'] = False


def myAnalysisSortWordcloud(PlatID, ProjID, mongodb_cfg, analysis, Condition, replaceCondition, rowDelete, TempID,
                            json_data, json_data_template, fileZipPath, dataSetIdFlag, reportError):
    for analysisRow in analysis:
        try:
            if str(analysisRow["index"]) == "480":
                testFlag = True
            if not os.path.exists(fileZipPath):break
            phrase, OptionID, noCondition, deleteRow, json_data_save, point, optionPoint, \
            idText, removeWord, addWord = "", "", "", "", True, "", None, "", None, None
            if "phrase" in analysisRow.keys():  phrase = analysisRow["phrase"]
            if "OptionID" in analysisRow.keys(): OptionID = analysisRow["OptionID"]
            if "noCondition" in analysisRow.keys(): noCondition = str(analysisRow["noCondition"]).strip()
            if "deleteRow" in analysisRow.keys(): deleteRow = analysisRow["deleteRow"]
            if "point" in analysisRow.keys(): point = analysisRow["point"]
            if "optionPoint" in analysisRow.keys(): optionPoint = analysisRow["optionPoint"]
            if "removeWord" in analysisRow.keys(): removeWord = analysisRow["removeWord"]
            if "addWord" in analysisRow.keys(): addWord = analysisRow["addWord"]
            if point == '':point = '2'
            if rowDelete: deleteRow = ""
            if not isinstance(deleteRow, dict) and str(deleteRow).strip() != "":
                if is_number(deleteRow):
                    if analysisRow["algorithm"] == "crosstabs" or analysisRow["algorithm"] == "crosstabsMultiple" or \
                            analysisRow["algorithm"] == "crosstabsSort":
                        deleteRow = {"total": int(deleteRow)}
                    else:
                        deleteRow = {"count": int(deleteRow)}
                else:
                    deleteRow = ''
            if replaceCondition is not None and "filter" in analysisRow and isinstance(analysisRow["filter"], dict) and\
                    str(analysisRow["filter"]) != "":
                for filterKey, filterValue in analysisRow["filter"].items():
                    for replaceItem in replaceCondition[0]:
                        for keyReplace, valueReplace in replaceItem.items():
                            if filterKey == keyReplace:
                                json_data_save = False
            if noCondition != "" and TempID != "" and json_data_template and json_data_save and \
                    'data' + str(analysisRow["index"]) in json_data_template['json_data'].keys():
                json_data['data' + str(analysisRow["index"])] = \
                    json_data_template['json_data']['data' + str(analysisRow["index"])]
            else:
                if dataSetIdFlag and 'condition' in dataSetIdFlag.keys() and 'dataSetId' in dataSetIdFlag.keys() and \
                        str(analysisRow["dataSourceId"]) in dataSetIdFlag['dataSetId'].keys():
                    copyCondition = copy.deepcopy(dataSetIdFlag['condition'][str(analysisRow["dataSourceId"])])
                else:
                    copyCondition = copy.deepcopy(Condition)
                if analysisRow["algorithm"] == "sort1":
                    datasource = mongo_sort_logic(PlatID, mongodb_cfg, ProjID,
                                                  str(analysisRow["dataSourceId"]),
                                                  analysisRow["VariableID1"],
                                                  analysisRow["VariableID2"],
                                                  analysisRow["VariableID3"],point, dataSetIdFlag,
                                                  caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "sort2":
                    if isinstance(phrase, list) and isinstance(OptionID, list):
                        phraseNew = {}
                        for optionIndex, optionItem in enumerate(OptionID):
                            if optionIndex < len(phrase):
                                phraseNew[optionItem] = phrase[optionIndex]
                        phrase = phraseNew
                    datasource = mongo_sort2_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                   analysisRow["variable"], phrase, point, optionPoint, dataSetIdFlag,
                                                   caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                 noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "crosstabsSort":
                    if isinstance(phrase, list) and isinstance(OptionID, list):
                        phraseNew = {}
                        for optionIndex, optionItem in enumerate(OptionID):
                            if optionIndex < len(phrase):
                                phraseNew[optionItem] = phrase[optionIndex]
                        phrase = phraseNew
                    datasource = mongo_crosstabsSort2_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                            analysisRow["RowID"], analysisRow["ColumnID"], phrase, point,
                                                            optionPoint, dataSetIdFlag, deleteRow, idText,
                                                   caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition, analysisRow,
                                                                 noCondition, json_data, replaceCondition))
                elif analysisRow["algorithm"] == "wordcloud":
                    datasource = mongo_wordcloud_logic(PlatID, mongodb_cfg, ProjID, str(analysisRow["dataSourceId"]),
                                                       analysisRow["variable"], phrase, dataSetIdFlag, removeWord, addWord,
                                                       caseCondition(PlatID, ProjID, mongodb_cfg, copyCondition,
                                                                     analysisRow,
                                                                     noCondition, json_data, replaceCondition))
                else:
                    datasource = None
                if datasource is not None and datasource:
                    datasource['head'][0]['noCondition'] = noCondition
                    json_data['data' + str(analysisRow["index"])] = json.dumps(datasource)
        except Exception as ex:
            reportError['data' + str(analysisRow["index"])] = str(ex)
            json_data['json_data_flag'] = False


def myJson_data_reset(json_data):
    for json_key, json_value in json_data.items():
        if json_key != 'json_data_flag' and ('percentileRank' in json.loads(json_value)['head'][0].keys() or
                                             'lengthFilter' in json.loads(json_value)['head'][0].keys()):
            if 'percentileRank' in json.loads(json_value)['head'][0].keys():
                percentileRank = json.loads(json_value)['head'][0]['percentileRank']
                if isinstance(percentileRank, list):
                    if percentileRank[0] in json_data.keys():
                        datasource = json.loads(json_data[percentileRank[0]])
                        if len(percentileRank) > 2:
                            averageString = '0'
                            for detailValidIndex, detailValidItem in enumerate(datasource["detailValid"]):
                                if percentileRank[2].strip() == str(detailValidItem['textRow']).strip():
                                    averageString = str(detailValidItem[percentileRank[1]])
                                json_data[percentileRank[0]]["detailValid"][detailValidIndex]['percentileRank'] = \
                                    returnPercentileRank(averageString, copy.deepcopy(datasource["detailValid"]))
                                break
                        else:
                            averageString = str(datasource["head"][0][percentileRank[1]])
                            datasource["head"][0]['percentileRank'] = \
                                returnPercentileRank(averageString,copy.deepcopy(json.loads(json_value)["detailValid"]))
                        json_data[percentileRank[0]] = json.dumps(datasource)
            if 'lengthFilter' in json.loads(json_value)['head'][0].keys():
                filterList, detailRemove, datasource = [], [], json.loads(json_value)
                lengthFilter = str(datasource['head'][0]['lengthFilter']['length']).split(':')
                lengthFilterData = json.loads(json_data[lengthFilter[0]])
                for detailValidItem in lengthFilterData["detailValid"]:
                    filterList.append(detailValidItem[lengthFilter[1]])
                for detailValidItem in datasource["detailValid"]:
                    if detailValidItem[lengthFilter[1]] not in filterList:
                        detailRemove.append(detailValidItem)
                if 'otherName' in datasource['head'][0]['lengthFilter'].keys():
                    num, perV, per = 0, 0.0, 0.0
                    for detailItem in detailRemove:
                        num += detailItem['count']
                        perV += detailItem['validpercent']
                        per += detailItem['percent']
                    datasource["detailValid"].append(dict(value=999999999,
                                                         text=datasource['head'][0]['lengthFilter']['otherName'],
                                                         count=int(num), validpercent=perV, percent=per))
                for detailItem in detailRemove:
                    datasource["detailValid"].remove(detailItem)
                json_data[json_key] = json.dumps(datasource)
    return json_data


def myTemplateUpdate(PlatID, ProjID, TempID, mongodb_cfg, templateItem):
    try:
        mongo_template_back_delete(PlatID, mongodb_cfg, ProjID, TempID)
        templateJson = dict(platId=PlatID, projId=ProjID, tempId=TempID, template=templateItem)
        mongo_template_back_insert(mongodb_cfg, templateJson)
    except Exception as ex:
        pass


def myTemplateCheck(PlatID, ProjID, TempID, mongodb_cfg, analysis):
    templateBack = mongo_template_back(PlatID, mongodb_cfg, ProjID, TempID)
    for templateBackItem in templateBack:
        templateBackData = templateBackItem["template"]
        for rowItem in templateBackData:
            if rowItem["type"] == "analy":
                analysisBack = rowItem["analy"]
                if json.dumps(analysisBack) == json.dumps(analysis):
                    return True
                else:
                    mongo_analysis_delete(PlatID, mongodb_cfg, ProjID, TempID)
                    return False
    return False


def myReport(documentPptx, content, json_data, chartfile, tableHead, replaceText, replaceChart, fileZipPath, edition,
             templateId, updatePhraseFlag, reportError):
    slideDelete = None
    try:
        #lock.acquire()
        if os.path.exists(fileZipPath):
            discriptionTitle, chartTitle, tableTitle = [], [], []
            for contentRow in content:
                if contentRow["type"] == "text" and 'title' in contentRow["content"].keys():
                    discriptionTitle.append(str(contentRow["content"]["title"]).strip())
                if contentRow["type"] == "wordchart" and 'position' in contentRow["content"].keys():
                    chartTitle.append(str(contentRow["content"]["position"]).strip())
                if contentRow["type"] == "table" and 'flag' in contentRow["content"].keys():
                    tableTitle.append(str(contentRow["content"]["flag"]).strip())
            textDiscription, tableDiscription, tableIndexDiscription, slideDelete = \
                pptxdiscriptionTextAndTable(documentPptx, discriptionTitle, chartTitle, tableTitle)
            if not updatePhraseFlag: slideDelete = None
        else:
            textDiscription, tableDiscription, tableIndexDiscription, slideDelete = '','','',None
        contentRowFinally, sameRowTable = None, []
        for contentRowIndex, contentRow in enumerate(content):
            if not os.path.exists(fileZipPath): break
            if contentRow["type"] == "text":
                if "data" not in contentRow["content"].keys() and "outColumn" not in contentRow["content"].keys() and \
                        contentRowIndex != len(content) - 1:
                    contentRowFinally = contentRow
                else:
                    try:
                        pptxdiscription(documentPptx, contentRow, json_data, chartfile, replaceText, textDiscription,
                                        tableDiscription, tableIndexDiscription, slideDelete)
                    except Exception as ex:
                        if "content" in contentRow.keys() and "title" in contentRow["content"].keys():
                            reportError[contentRow["content"]["title"]] = str(ex)
                        print(ex)
                        pass
            elif contentRow["type"] == "chart" or contentRow["type"] == "wordchart":
                try:
                    pptxcharts(documentPptx, contentRow, json_data, chartfile, replaceChart, slideDelete, edition, templateId)
                except Exception as ex:
                    if "content" in contentRow.keys() and "position" in contentRow["content"].keys():
                        reportError[contentRow["content"]["position"]] = str(ex)
                    pass
            elif contentRow["type"] == "table":
                try:
                    pptxtable(documentPptx, contentRow, json_data, tableHead, slideDelete,
                                                 sameRowTable, replaceChart)
                except Exception as ex:
                    if "content" in contentRow.keys() and "flag" in contentRow["content"].keys():
                        reportError[contentRow["content"]["flag"]] = str(ex)
                    pass
            else:
                pass
        if contentRowFinally is not None:
            try:
                pptxdiscription(documentPptx, contentRowFinally, json_data, chartfile, replaceText, textDiscription,
                                tableDiscription, tableIndexDiscription, slideDelete)
            except Exception as ex:
                if "content" in contentRowFinally.keys() and "title" in contentRowFinally["content"].keys():
                    reportError[contentRowFinally["content"]["title"]] = str(ex)
                pass
        if os.path.exists(fileZipPath):pptxdiscriptionReplace(documentPptx)
    except Exception as ex:
        my_log.error(ex)
        pass
    finally:
        #lock.release()
        pass
    return slideDelete


def check_json_format(raw_msg):
    if isinstance(raw_msg, str):
        try:
            json.loads(raw_msg)
            for key, value in json.loads(str(raw_msg).strip()).items():
                return True
        except Exception as e:
            pass
        return False
    else:
        return False


class myCalculation:
    def __init__(self):
        self._obj_mul = re.compile(r"(-?\d+\.?\d*)\*(-?\d+\.?\d*)")  # 乘法
        self._obj_div = re.compile(r"(-?\d+\.?\d*)/(-?\d+\.?\d*)")  # 除法
        self._obj_add = re.compile(r"(-?\d+\.?\d*)\+(-?\d+\.?\d*)")  # 加法
        self._obj_sub = re.compile(r"(-?\d+\.?\d*)-(-?\d+\.?\d*)")  # 减法
        self._obj_f = re.compile(r"\(?\+?-?\d+\)?")  # 检查括号内是否运算完毕规则
        self._obj_k = re.compile(r"\([^()]+\)")  # 寻找最内层括号规则
        self._obj_che = re.compile(r"[^0-9+\-*/()\s.]")  # 匹配输入非法字符
        self._PREC = '{:+.15f}'  # 计算精度 15代表15位小数

    def count(self, calculation):
        """
         计算没有括号的式子
        :type calculation: object
        :return:
        """
        calculationString = self.rm_SP(calculation)
        while True:
            if self._obj_div.search(calculationString):  # 除法(必须先判断)
                exp = re.split(r'/', self._obj_div.search(calculationString).group())
                answer = float(exp[0]) / float(exp[1])
                calculationString = self._obj_div.sub(self._PREC.format(answer), calculationString, 1)
            elif self._obj_mul.search(calculationString):  # 乘法
                exp = re.split(r'\*', self._obj_mul.search(calculationString).group())
                answer = float(exp[0]) * float(exp[1])
                calculationString = self._obj_mul.sub(self._PREC.format(answer), calculationString, 1)
            elif self._obj_add.search(calculationString):  # 加法
                exp = re.split(r'\+', self._obj_add.search(calculationString).group())
                answer = float(exp[0]) + float(exp[1])
                calculationString = self._obj_add.sub(self._PREC.format(answer), calculationString, 1)
            elif self._obj_sub.search(calculationString):  # 减法
                exp = re.split(r'-', self._obj_sub.search(calculationString).group())
                if exp[0] == "":  # 前面有负号的时候
                    answer = 0 - float(exp[1]) - float(exp[2])
                    calculationString = self._obj_sub.sub(self._PREC.format(answer), calculationString, 1)
                else:
                    answer = float(exp[0]) - float(exp[1])
                    calculationString = self._obj_sub.sub(self._PREC.format(answer), calculationString, 1)
            elif self._obj_f.search(calculationString):  # 结束循环
                calculationString = re.sub('\(|\)|', '', calculationString)
                return calculationString
            calculationString = self.rm_SP(calculationString)  # 去除多余的符号

    @staticmethod
    def rm_SP(calculationString):
        """
        去除符号
        :param calculationString:
        :return:
        """
        calculationString = re.sub('\+\+','+',calculationString)
        calculationString = re.sub('--', '+', calculationString)
        calculationString = re.sub('\+-', '-', calculationString)
        calculationString = re.sub('-\+', '-', calculationString)
        calculationString = re.sub('/\+', '/', calculationString)
        calculationString = re.sub('\*\+', '*', calculationString)
        calculationString = re.sub('^\+', '', calculationString)
        return calculationString

    def rm_PAR(self, calculationString):
        """
        计算括号里
        :param calculationString:
        :return:
        """
        calculationString = self.rm_SP(calculationString)
        list_m = self._obj_k.findall(calculationString)
        list_map = map(self.count, list_m)
        for i in range(len(list_m)):
            calculationString = calculationString.replace(list_m[i], list_map.__next__(), 1)
        return calculationString

    def main(self, calculationString):
        """
        主函数，循环计算
        :param calculationString:
        :return
        """
        try:
            if self.checkout(calculationString):
                calculationString = re.sub('\s', '', calculationString)  # 去掉空格
                while True:
                    if self._obj_k.search(calculationString):  # 是否还存在括号
                        calculationString = self.rm_PAR(calculationString)
                        continue
                    answer = self.count(calculationString)
                    return answer
        except Exception as e:
            pass
        return ""

    def checkout(self, calculationString):
        """
        校验输入是否合法
        :param calculationString:
        :return
        """
        if len(re.findall('\(', calculationString)) != len(re.findall('\)', calculationString)):
            return False
        elif not (isinstance(self._obj_che.findall(calculationString), list) and
                  len(self._obj_che.findall(calculationString))) == 0:
            return False
        return True


if __name__ == '__main__':
    PlatID = "1"
    #ProjID = "1"
    #mongodb_cfg = 'readInfo'
    #templateFileServerUrl = ""
    nacos_main(None)
    ProjID = ""     #"6268a6f79651d75b007e9c10"
    mongodb_cfg, maxResponseCount,templateFileServerUrl, redis_cfg = nacos_py('192.168.2.160:3000')
    #ProjID = "627ba5caf04f201d935fd304"
    #PlatID = ""
    #mongodb_cfg,maxResponseCount = nacos_py('medudata.bjmu.edu.cn')
    TokenID = ""

    TempID = "65c1ae2eb8bdd34db38ab5b7"
    fileName = "报告"
    caseFilter = "SZYX"
    edition = "ppt"
    CasesCondition = None
    fileGroup = ['管理学院']

    updateFlag = False
    updatePhraseFlag = True
    myReportPPTXMainJava(PlatID, ProjID, TempID, TokenID, mongodb_cfg, caseFilter, fileGroup, fileName, edition,
                         updateFlag, templateFileServerUrl, redis_cfg, updatePhraseFlag, CasesCondition)
    print("报告生成完成！")
    #for fileItem in fileGroup:
        #NewFileName = fileItem + '2020年度临床医学专业（本科）水平测试成绩分析报告'
        #CasesCondition = dict(学校名称=fileItem)
        #data = myReportCreate(PlatID, ProjID, TempID, NewFileName, CasesCondition)